Просмотр исходного кода

Modified status_calc_* to support multiple options. (Hercules 6f77d07)

aleos89 11 лет назад
Родитель
Сommit
2732176786
16 измененных файлов с 264 добавлено и 241 удалено
  1. 9 7
      src/map/atcommand.c
  2. 27 12
      src/map/battle.c
  3. 1 1
      src/map/chrif.c
  4. 1 1
      src/map/clif.c
  5. 1 1
      src/map/elemental.c
  6. 1 1
      src/map/guild.c
  7. 10 9
      src/map/homunculus.c
  8. 1 2
      src/map/itemdb.c
  9. 7 11
      src/map/mercenary.c
  10. 4 5
      src/map/mob.c
  11. 45 53
      src/map/pc.c
  12. 3 0
      src/map/pc.h
  13. 30 33
      src/map/pet.c
  14. 41 42
      src/map/script.c
  15. 60 47
      src/map/status.c
  16. 23 16
      src/map/status.h

+ 9 - 7
src/map/atcommand.c

@@ -1398,6 +1398,7 @@ ACMD_FUNC(baselevelup)
 
 
 		sd->status.status_point += status_point;
 		sd->status.status_point += status_point;
 		sd->status.base_level += (unsigned int)level;
 		sd->status.base_level += (unsigned int)level;
+		status_calc_pc(sd, SCO_FORCE);
 		status_percent_heal(&sd->bl, 100, 100);
 		status_percent_heal(&sd->bl, 100, 100);
 		clif_misceffect(&sd->bl, 0);
 		clif_misceffect(&sd->bl, 0);
 		clif_displaymessage(fd, msg_txt(sd,21)); // Base level raised.
 		clif_displaymessage(fd, msg_txt(sd,21)); // Base level raised.
@@ -1419,13 +1420,13 @@ ACMD_FUNC(baselevelup)
 			sd->status.status_point -= status_point;
 			sd->status.status_point -= status_point;
 		sd->status.base_level -= (unsigned int)level;
 		sd->status.base_level -= (unsigned int)level;
 		clif_displaymessage(fd, msg_txt(sd,22)); // Base level lowered.
 		clif_displaymessage(fd, msg_txt(sd,22)); // Base level lowered.
+		status_calc_pc(sd, SCO_FORCE);
 	}
 	}
 	sd->status.base_exp = 0;
 	sd->status.base_exp = 0;
 	clif_updatestatus(sd, SP_STATUSPOINT);
 	clif_updatestatus(sd, SP_STATUSPOINT);
 	clif_updatestatus(sd, SP_BASELEVEL);
 	clif_updatestatus(sd, SP_BASELEVEL);
 	clif_updatestatus(sd, SP_BASEEXP);
 	clif_updatestatus(sd, SP_BASEEXP);
 	clif_updatestatus(sd, SP_NEXTBASEEXP);
 	clif_updatestatus(sd, SP_NEXTBASEEXP);
-	status_calc_pc(sd, 0);
 	pc_baselevelchanged(sd);
 	pc_baselevelchanged(sd);
 	if(sd->status.party_id)
 	if(sd->status.party_id)
 		party_send_levelup(sd);
 		party_send_levelup(sd);
@@ -1479,7 +1480,7 @@ ACMD_FUNC(joblevelup)
 	clif_updatestatus(sd, SP_JOBEXP);
 	clif_updatestatus(sd, SP_JOBEXP);
 	clif_updatestatus(sd, SP_NEXTJOBEXP);
 	clif_updatestatus(sd, SP_NEXTJOBEXP);
 	clif_updatestatus(sd, SP_SKILLPOINT);
 	clif_updatestatus(sd, SP_SKILLPOINT);
-	status_calc_pc(sd, 0);
+	status_calc_pc(sd, SCO_FORCE);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2539,7 +2540,7 @@ ACMD_FUNC(param)
 		*status[i] = new_value;
 		*status[i] = new_value;
 		clif_updatestatus(sd, SP_STR + i);
 		clif_updatestatus(sd, SP_STR + i);
 		clif_updatestatus(sd, SP_USTR + i);
 		clif_updatestatus(sd, SP_USTR + i);
-		status_calc_pc(sd, 0);
+		status_calc_pc(sd, SCO_FORCE);
 		clif_displaymessage(fd, msg_txt(sd,42)); // Stat changed.
 		clif_displaymessage(fd, msg_txt(sd,42)); // Stat changed.
 	} else {
 	} else {
 		if (value < 0)
 		if (value < 0)
@@ -2610,7 +2611,7 @@ ACMD_FUNC(stat_all)
 	}
 	}
 
 
 	if (count > 0) { // if at least 1 stat modified
 	if (count > 0) { // if at least 1 stat modified
-		status_calc_pc(sd, 0);
+		status_calc_pc(sd, SCO_FORCE);
 		clif_displaymessage(fd, msg_txt(sd,84)); // All stats changed!
 		clif_displaymessage(fd, msg_txt(sd,84)); // All stats changed!
 	} else {
 	} else {
 		if (value < 0)
 		if (value < 0)
@@ -7146,13 +7147,14 @@ ACMD_FUNC(homlevel)
 
 
 	for (i = 1; i <= level && hd->exp_next; i++){
 	for (i = 1; i <= level && hd->exp_next; i++){
 		hd->homunculus.exp += hd->exp_next;
 		hd->homunculus.exp += hd->exp_next;
-		if( !hom_levelup(hd) ){
+		if( !hom_levelup(hd) )
 			break;
 			break;
-		}
 	}
 	}
-	status_calc_homunculus(hd,0);
+
+	status_calc_homunculus(hd, SCO_NONE);
 	status_percent_heal(&hd->bl, 100, 100);
 	status_percent_heal(&hd->bl, 100, 100);
 	clif_specialeffect(&hd->bl,568,AREA);
 	clif_specialeffect(&hd->bl,568,AREA);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 27 - 12
src/map/battle.c

@@ -213,16 +213,22 @@ struct delay_damage {
 	enum damage_lv dmg_lv;
 	enum damage_lv dmg_lv;
 	unsigned short attack_type;
 	unsigned short attack_type;
 	bool additional_effects;
 	bool additional_effects;
+	enum bl_type src_type;
 };
 };
 
 
 int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
 int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
 	struct delay_damage *dat = (struct delay_damage *)data;
 	struct delay_damage *dat = (struct delay_damage *)data;
 
 
 	if ( dat ) {
 	if ( dat ) {
-		struct block_list* src;
+		struct block_list* src = NULL;
 		struct block_list* target = map_id2bl(dat->target_id);
 		struct block_list* target = map_id2bl(dat->target_id);
 
 
-		if( !target || status_isdead(target) ) {/* nothing we can do */
+		if( !target || status_isdead(target) ) { /* Nothing we can do */
+			if( dat->src_type == BL_PC && (src = map_id2bl(dat->src_id)) &&
+				--((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
+				((TBL_PC*)src)->state.hold_recalc = 0;
+				status_calc_pc(((TBL_PC*)src), SCO_FORCE);
+			}
 			ers_free(delay_damage_ers, dat);
 			ers_free(delay_damage_ers, dat);
 			return 0;
 			return 0;
 		}
 		}
@@ -248,12 +254,17 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) {
 			status_fix_damage(target, target, dat->damage, dat->delay);
 			status_fix_damage(target, target, dat->damage, dat->delay);
 			map_freeblock_unlock();
 			map_freeblock_unlock();
 		}
 		}
+
+		if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
+			((TBL_PC*)src)->state.hold_recalc = 0;
+			status_calc_pc(((TBL_PC*)src), SCO_FORCE);
+		}
 	}
 	}
 	ers_free(delay_damage_ers, dat);
 	ers_free(delay_damage_ers, dat);
 	return 0;
 	return 0;
 }
 }
 
 
-int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects)
+int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects)
 {
 {
 	struct delay_damage *dat;
 	struct delay_damage *dat;
 	struct status_change *sc;
 	struct status_change *sc;
@@ -286,18 +297,24 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src,
 	dat->delay = ddelay;
 	dat->delay = ddelay;
 	dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
 	dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
 	dat->additional_effects = additional_effects;
 	dat->additional_effects = additional_effects;
+	dat->src_type = src->type;
 	if (src->type != BL_PC && amotion > 1000)
 	if (src->type != BL_PC && amotion > 1000)
 		amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
 		amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
 
 
+	if( src->type == BL_PC )
+		((TBL_PC*)src)->delayed_damage++;
+
 	add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat);
 	add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat);
 
 
 	return 0;
 	return 0;
 }
 }
-int battle_attr_ratio(int atk_elem,int def_type, int def_lv){
+
+int battle_attr_ratio(int atk_elem,int def_type, int def_lv) {
 	if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_ALL)
 	if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_ALL)
 		return 100;
 		return 100;
 	if (def_type < ELE_NEUTRAL || def_type > ELE_ALL || def_lv < 1 || def_lv > 4)
 	if (def_type < ELE_NEUTRAL || def_type > ELE_ALL || def_lv < 1 || def_lv > 4)
 		return 100;
 		return 100;
+
 	return attr_fix_table[def_lv-1][atk_elem][def_type];
 	return attr_fix_table[def_lv-1][atk_elem][def_type];
 }
 }
 
 
@@ -2569,12 +2586,10 @@ struct Damage battle_calc_damage_parts(struct Damage wd, struct block_list *src,
 	wd.statusAtk += battle_calc_status_attack(sstatus, EQI_HAND_R);
 	wd.statusAtk += battle_calc_status_attack(sstatus, EQI_HAND_R);
 	wd.statusAtk2 += battle_calc_status_attack(sstatus, EQI_HAND_L);
 	wd.statusAtk2 += battle_calc_status_attack(sstatus, EQI_HAND_L);
 
 
-	if (skill_id || (sd && sd->sc.data[SC_SEVENWIND])) {
-		 // Mild Wind applies element to status ATK as well as weapon ATK [helvetica]
+	if (skill_id || (sd && sd->sc.data[SC_SEVENWIND])) { // Mild Wind applies element to status ATK as well as weapon ATK [helvetica]
 		wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv);
-	}
-	else { // status atk is considered neutral on normal attacks [helvetica]
+	} else { // status atk is considered neutral on normal attacks [helvetica]
 		wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 		wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
 	}
 	}
@@ -4775,6 +4790,7 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr
 		}
 		}
 	}
 	}
 }
 }
+
 /*============================================
 /*============================================
  * Calculate "weapon"-type attacks and skills
  * Calculate "weapon"-type attacks and skills
  *--------------------------------------------
  *--------------------------------------------
@@ -5886,7 +5902,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 
 
 	memset(&md,0,sizeof(md));
 	memset(&md,0,sizeof(md));
 
 
-	if( src == NULL || target == NULL ){
+	if (src == NULL || target == NULL) {
 		nullpo_info(NLP_MARK);
 		nullpo_info(NLP_MARK);
 		return md;
 		return md;
 	}
 	}
@@ -5918,8 +5934,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 	//Skill Range Criteria
 	//Skill Range Criteria
 	md.flag |= battle_range_type(src, target, skill_id, skill_lv);
 	md.flag |= battle_range_type(src, target, skill_id, skill_lv);
 
 
-	switch( skill_id )
-	{
+	switch (skill_id) {
 	case NC_MAGMA_ERUPTION:
 	case NC_MAGMA_ERUPTION:
 		md.damage = 1200 + 400 * skill_lv;
 		md.damage = 1200 + 400 * skill_lv;
 		break;
 		break;
@@ -7281,7 +7296,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 			if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))))
 			if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild))))
 				state |= BCT_GUILD;
 				state |= BCT_GUILD;
 		}
 		}
-    } //end non pvp/gvg chk rivality
+	} //end non pvp/gvg chk rivality
 
 
 	if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
 	if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
 		state = BCT_NEUTRAL;
 		state = BCT_NEUTRAL;

+ 1 - 1
src/map/chrif.c

@@ -1897,7 +1897,7 @@ int chrif_load_bsdata(int fd) {
 		calc = true;
 		calc = true;
 	}
 	}
 	if (calc)
 	if (calc)
-		status_calc_pc(sd,false);
+		status_calc_pc(sd,SCO_NONE);
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 1
src/map/clif.c

@@ -9758,7 +9758,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		}
 		}
 
 
 		map_iwall_get(sd); // Updates Walls Info on this Map to Client
 		map_iwall_get(sd); // Updates Walls Info on this Map to Client
-		status_calc_pc(sd, false); // Some conditions are map-dependent so we must recalculate
+		status_calc_pc(sd, SCO_NONE); // Some conditions are map-dependent so we must recalculate
 		sd->state.changemap = false;
 		sd->state.changemap = false;
 
 
 		// Instances do not need their own channels
 		// Instances do not need their own channels

+ 1 - 1
src/map/elemental.c

@@ -263,7 +263,7 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
 		ed->bl.y = ed->ud.to_y;
 		ed->bl.y = ed->ud.to_y;
 
 
 		map_addiddb(&ed->bl);
 		map_addiddb(&ed->bl);
-		status_calc_elemental(ed,1);
+		status_calc_elemental(ed,SCO_FIRST);
 		ed->last_spdrain_time = ed->last_thinktime = gettick();
 		ed->last_spdrain_time = ed->last_thinktime = gettick();
 		ed->summon_timer = INVALID_TIMER;
 		ed->summon_timer = INVALID_TIMER;
 		ed->masterteleport_timer = INVALID_TIMER;
 		ed->masterteleport_timer = INVALID_TIMER;

+ 1 - 1
src/map/guild.c

@@ -1876,7 +1876,7 @@ int guild_castledatasave(int castle_id, int index, int value) {
 		for (i = 0; i < MAX_GUARDIANS; i++){
 		for (i = 0; i < MAX_GUARDIANS; i++){
 			struct mob_data *gd;
 			struct mob_data *gd;
 			if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL)
 			if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL)
-				status_calc_mob(gd, 0);
+				status_calc_mob(gd, SCO_NONE);
 		}
 		}
 		break;
 		break;
 	}
 	}

+ 10 - 9
src/map/homunculus.c

@@ -300,7 +300,7 @@ void hom_skillup(struct homun_data *hd,uint16 skill_id)
 	{
 	{
 		hd->homunculus.hskill[i].lv++;
 		hd->homunculus.hskill[i].lv++;
 		hd->homunculus.skillpts-- ;
 		hd->homunculus.skillpts-- ;
-		status_calc_homunculus(hd,0);
+		status_calc_homunculus(hd, SCO_NONE);
 		if (hd->master) {
 		if (hd->master) {
 			clif_homskillup(hd->master, skill_id);
 			clif_homskillup(hd->master, skill_id);
 			clif_hominfo(hd->master,hd,0);
 			clif_hominfo(hd->master,hd,0);
@@ -417,8 +417,7 @@ int hom_evolution(struct homun_data *hd)
 	struct map_session_data *sd;
 	struct map_session_data *sd;
 	nullpo_ret(hd);
 	nullpo_ret(hd);
 
 
-	if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class)
-	{
+	if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) {
 		clif_emotion(&hd->bl, E_SWT);
 		clif_emotion(&hd->bl, E_SWT);
 		return 0 ;
 		return 0 ;
 	}
 	}
@@ -456,7 +455,7 @@ int hom_evolution(struct homun_data *hd)
 	//status_Calc flag&1 will make current HP/SP be reloaded from hom structure
 	//status_Calc flag&1 will make current HP/SP be reloaded from hom structure
 	hom->hp = hd->battle_status.hp;
 	hom->hp = hd->battle_status.hp;
 	hom->sp = hd->battle_status.sp;
 	hom->sp = hd->battle_status.sp;
-	status_calc_homunculus(hd,1);
+	status_calc_homunculus(hd, SCO_FIRST);
 
 
 	if (!(battle_config.hom_setting&0x2))
 	if (!(battle_config.hom_setting&0x2))
 		skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
 		skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
@@ -510,7 +509,7 @@ int hom_mutate(struct homun_data *hd, int homun_id)
 	hom->hp = hd->battle_status.hp;
 	hom->hp = hd->battle_status.hp;
 	hom->sp = hd->battle_status.sp;
 	hom->sp = hd->battle_status.sp;
 	hom->prev_class = prev_class;
 	hom->prev_class = prev_class;
-	status_calc_homunculus(hd,1);
+	status_calc_homunculus(hd, SCO_FIRST);
 
 
 	if (!(battle_config.hom_setting&0x2))
 	if (!(battle_config.hom_setting&0x2))
 		skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
 		skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
@@ -556,7 +555,7 @@ int hom_gainexp(struct homun_data *hd,int exp)
 		hd->homunculus.exp = 0 ;
 		hd->homunculus.exp = 0 ;
 
 
 	clif_specialeffect(&hd->bl,568,AREA);
 	clif_specialeffect(&hd->bl,568,AREA);
-	status_calc_homunculus(hd,0);
+	status_calc_homunculus(hd, SCO_NONE);
 	status_percent_heal(&hd->bl, 100, 100);
 	status_percent_heal(&hd->bl, 100, 100);
 	return 0;
 	return 0;
 }
 }
@@ -785,7 +784,8 @@ int hom_search(int key,int type)
 }
 }
 
 
 // Create homunc structure
 // Create homunc structure
-void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) {
+void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom)
+{
 	struct homun_data *hd;
 	struct homun_data *hd;
 	int i = 0;
 	int i = 0;
 
 
@@ -823,7 +823,8 @@ void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) {
 	hd->bl.y = hd->ud.to_y;
 	hd->bl.y = hd->ud.to_y;
 
 
 	map_addiddb(&hd->bl);
 	map_addiddb(&hd->bl);
-	status_calc_homunculus(hd,1);
+	status_calc_homunculus(hd, SCO_FIRST);
+	status_percent_heal(&hd->bl, 100, 100);
 
 
 	hd->hungry_timer = INVALID_TIMER;
 	hd->hungry_timer = INVALID_TIMER;
 	hd->masterteleport_timer = INVALID_TIMER;
 	hd->masterteleport_timer = INVALID_TIMER;
@@ -1093,7 +1094,7 @@ int hom_shuffle(struct homun_data *hd)
 	memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
 	memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill));
 	hd->homunculus.skillpts = skillpts;
 	hd->homunculus.skillpts = skillpts;
 	clif_homskillinfoblock(sd);
 	clif_homskillinfoblock(sd);
-	status_calc_homunculus(hd,0);
+	status_calc_homunculus(hd, SCO_NONE);
 	status_percent_heal(&hd->bl, 100, 100);
 	status_percent_heal(&hd->bl, 100, 100);
 	clif_specialeffect(&hd->bl,568,AREA);
 	clif_specialeffect(&hd->bl,568,AREA);
 
 

+ 1 - 2
src/map/itemdb.c

@@ -1753,14 +1753,13 @@ void itemdb_reload(void) {
 			sd->combos.id = NULL;
 			sd->combos.id = NULL;
 			sd->combos.count = 0;
 			sd->combos.count = 0;
 			if( pc_load_combo(sd) > 0 )
 			if( pc_load_combo(sd) > 0 )
-				status_calc_pc(sd,0);
+				status_calc_pc(sd, SCO_FORCE);
 		}
 		}
 
 
 	}
 	}
 	mapit_free(iter);
 	mapit_free(iter);
 }
 }
 
 
-
 /**
 /**
 * Finalizing Item DB
 * Finalizing Item DB
 */
 */

+ 7 - 11
src/map/mercenary.c

@@ -341,7 +341,8 @@ void merc_contract_init(struct mercenary_data *md) {
  * @param flag : if inter-serv request was sucessfull
  * @param flag : if inter-serv request was sucessfull
  * @return false:failure, true:sucess
  * @return false:failure, true:sucess
  */
  */
-bool mercenary_recv_data(struct s_mercenary *merc, bool flag){
+bool mercenary_recv_data(struct s_mercenary *merc, bool flag)
+{
 	struct map_session_data *sd;
 	struct map_session_data *sd;
 	struct mercenary_data *md;
 	struct mercenary_data *md;
 	struct s_mercenary_db *db;
 	struct s_mercenary_db *db;
@@ -349,15 +350,13 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){
 
 
 	if( (sd = map_charid2sd(merc->char_id)) == NULL )
 	if( (sd = map_charid2sd(merc->char_id)) == NULL )
 		return false;
 		return false;
-	if( !flag || i < 0 )
-	{ // Not created - loaded - DB info
+	if( !flag || i < 0 ) { // Not created - loaded - DB info
 		sd->status.mer_id = 0;
 		sd->status.mer_id = 0;
 		return false;
 		return false;
 	}
 	}
 
 
 	db = &mercenary_db[i];
 	db = &mercenary_db[i];
-	if( !sd->md )
-	{
+	if( !sd->md ) {
 		sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data));
 		sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data));
 		md->bl.type = BL_MER;
 		md->bl.type = BL_MER;
 		md->bl.id = npc_get_new_npc_id();
 		md->bl.id = npc_get_new_npc_id();
@@ -379,13 +378,11 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){
 		md->bl.y = md->ud.to_y;
 		md->bl.y = md->ud.to_y;
 
 
 		map_addiddb(&md->bl);
 		map_addiddb(&md->bl);
-		status_calc_mercenary(md,1);
+		status_calc_mercenary(md, SCO_FIRST);
 		md->contract_timer = INVALID_TIMER;
 		md->contract_timer = INVALID_TIMER;
 		md->masterteleport_timer = INVALID_TIMER;
 		md->masterteleport_timer = INVALID_TIMER;
 		merc_contract_init(md);
 		merc_contract_init(md);
-	}
-	else
-	{
+	} else {
 		memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary));
 		memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary));
 		md = sd->md;
 		md = sd->md;
 	}
 	}
@@ -394,8 +391,7 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){
 		mercenary_set_calls(md, 1);
 		mercenary_set_calls(md, 1);
 	sd->status.mer_id = merc->mercenary_id;
 	sd->status.mer_id = merc->mercenary_id;
 
 
-	if( md && md->bl.prev == NULL && sd->bl.prev != NULL )
-	{
+	if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) {
 		if(map_addblock(&md->bl))
 		if(map_addblock(&md->bl))
 			return false;
 			return false;
 		clif_spawn(&md->bl);
 		clif_spawn(&md->bl);

+ 4 - 5
src/map/mob.c

@@ -612,7 +612,7 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d
 	memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
 	memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH);
 	md->guardian_data->guardup_lv = guardup_lv;
 	md->guardian_data->guardup_lv = guardup_lv;
 	if( guardup_lv )
 	if( guardup_lv )
-		status_calc_mob(md, 0); //Give bonuses.
+		status_calc_mob(md, SCO_NONE); //Give bonuses.
 	return 0;
 	return 0;
 }
 }
 
 
@@ -943,14 +943,13 @@ int mob_spawn (struct mob_data *md)
 	}
 	}
 
 
 	memset(&md->state, 0, sizeof(md->state));
 	memset(&md->state, 0, sizeof(md->state));
-	status_calc_mob(md, 1);
+	status_calc_mob(md, SCO_FIRST);
 	md->attacked_id = 0;
 	md->attacked_id = 0;
 	md->target_id = 0;
 	md->target_id = 0;
 	md->move_fail_count = 0;
 	md->move_fail_count = 0;
 	md->ud.state.attack_continue = 0;
 	md->ud.state.attack_continue = 0;
 	md->ud.target_to = 0;
 	md->ud.target_to = 0;
-	if( md->spawn_timer != INVALID_TIMER )
-	{
+	if( md->spawn_timer != INVALID_TIMER ) {
 		delete_timer(md->spawn_timer, mob_delayspawn);
 		delete_timer(md->spawn_timer, mob_delayspawn);
 		md->spawn_timer = INVALID_TIMER;
 		md->spawn_timer = INVALID_TIMER;
 	}
 	}
@@ -2796,7 +2795,7 @@ int mob_class_change (struct mob_data *md, int mob_id)
 	unit_skillcastcancel(&md->bl, 0);
 	unit_skillcastcancel(&md->bl, 0);
 	status_set_viewdata(&md->bl, mob_id);
 	status_set_viewdata(&md->bl, mob_id);
 	clif_mob_class_change(md,md->vd->class_);
 	clif_mob_class_change(md,md->vd->class_);
-	status_calc_mob(md, 1);
+	status_calc_mob(md,SCO_FIRST);
 	md->ud.state.speed_changed = 1; //Speed change update.
 	md->ud.state.speed_changed = 1; //Speed change update.
 
 
 	if (battle_config.monster_class_change_recover) {
 	if (battle_config.monster_class_change_recover) {

+ 45 - 53
src/map/pc.c

@@ -1093,6 +1093,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	sd->guild_x = -1;
 	sd->guild_x = -1;
 	sd->guild_y = -1;
 	sd->guild_y = -1;
 
 
+	sd->delayed_damage = 0;
+
 	// Event Timers
 	// Event Timers
 	for( i = 0; i < MAX_EVENTTIMER; i++ )
 	for( i = 0; i < MAX_EVENTTIMER; i++ )
 		sd->eventtimer[i] = INVALID_TIMER;
 		sd->eventtimer[i] = INVALID_TIMER;
@@ -1313,7 +1315,7 @@ int pc_reg_received(struct map_session_data *sd)
 	pc_check_available_item(sd); // Check for invalid(ated) items.
 	pc_check_available_item(sd); // Check for invalid(ated) items.
 	pc_load_combo(sd);
 	pc_load_combo(sd);
 
 
-	status_calc_pc(sd,1);
+	status_calc_pc(sd, (enum e_status_calc_opt)(SCO_FIRST|SCO_FORCE));
 	chrif_scdata_request(sd->status.account_id, sd->status.char_id);
 	chrif_scdata_request(sd->status.account_id, sd->status.char_id);
 	chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id);
 	chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id);
 	chrif_bsdata_request(sd->status.char_id);
 	chrif_bsdata_request(sd->status.char_id);
@@ -2070,7 +2072,7 @@ void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
 
 
 	autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus);
 	autobonus->active = add_timer(gettick()+autobonus->duration, pc_endautobonus, sd->bl.id, (intptr_t)autobonus);
 	sd->state.autobonus |= autobonus->pos;
 	sd->state.autobonus |= autobonus->pos;
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 }
 }
 
 
 int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
 int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
@@ -2083,7 +2085,7 @@ int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	autobonus->active = INVALID_TIMER;
 	autobonus->active = INVALID_TIMER;
 	sd->state.autobonus &= ~autobonus->pos;
 	sd->state.autobonus &= ~autobonus->pos;
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3660,10 +3662,10 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
 			} else
 			} else
 				clif_addskill(sd,id);
 				clif_addskill(sd,id);
 			if( !skill_get_inf(id) ) //Only recalculate for passive skills.
 			if( !skill_get_inf(id) ) //Only recalculate for passive skills.
-				status_calc_pc(sd, 0);
+				status_calc_pc(sd, SCO_NONE);
 			break;
 			break;
 		case 1: //Item bonus skill.
 		case 1: //Item bonus skill.
-			if( sd->status.skill[id].id == id ){
+			if( sd->status.skill[id].id == id ) {
 				if( sd->status.skill[id].lv >= level )
 				if( sd->status.skill[id].lv >= level )
 					return 0;
 					return 0;
 				if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
 				if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level.
@@ -3675,7 +3677,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
 			sd->status.skill[id].lv = level;
 			sd->status.skill[id].lv = level;
 			break;
 			break;
 		case 2: //Add skill bonus on top of what you had.
 		case 2: //Add skill bonus on top of what you had.
-			if( sd->status.skill[id].id == id ){
+			if( sd->status.skill[id].id == id ) {
 				if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
 				if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT )
 					sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level.
 					sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level.
 			} else {
 			} else {
@@ -3694,7 +3696,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag)
 			} else
 			} else
 				clif_addskill(sd,id);
 				clif_addskill(sd,id);
 			if( !skill_get_inf(id) ) //Only recalculate for passive skills.
 			if( !skill_get_inf(id) ) //Only recalculate for passive skills.
-				status_calc_pc(sd, 0);
+				status_calc_pc(sd, SCO_NONE);
 			break;
 			break;
 		default: //Unknown flag?
 		default: //Unknown flag?
 			return 0;
 			return 0;
@@ -4314,6 +4316,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
 		return 0;
 		return 0;
 
 
 	if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) {
 	if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) {
+		clif_msgtable(sd->fd,ITEM_NOUSE_SITTING);
 		return 0; // You cannot use this item while sitting.
 		return 0; // You cannot use this item while sitting.
 	}
 	}
 
 
@@ -4478,7 +4481,7 @@ int pc_useitem(struct map_session_data *sd,int n)
 
 
 	nullpo_ret(sd);
 	nullpo_ret(sd);
 
 
-	if( sd->npc_id ){
+	if (sd->npc_id) {
 #ifdef RENEWAL
 #ifdef RENEWAL
 		clif_msg(sd, USAGE_FAIL); // TODO look for the client date that has this message.
 		clif_msg(sd, USAGE_FAIL); // TODO look for the client date that has this message.
 		return 0;
 		return 0;
@@ -4489,7 +4492,7 @@ int pc_useitem(struct map_session_data *sd,int n)
 	}
 	}
 	item = sd->status.inventory[n];
 	item = sd->status.inventory[n];
 	id = sd->inventory_data[n];
 	id = sd->inventory_data[n];
-	
+
 	if (item.nameid <= 0 || item.amount <= 0)
 	if (item.nameid <= 0 || item.amount <= 0)
 		return 0;
 		return 0;
 
 
@@ -5933,13 +5936,13 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
 	} while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
 	} while ((next=pc_nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
 
 
 	if (battle_config.pet_lv_rate && sd->pd)	//<Skotlex> update pet's level
 	if (battle_config.pet_lv_rate && sd->pd)	//<Skotlex> update pet's level
-		status_calc_pet(sd->pd,0);
+		status_calc_pet(sd->pd,SCO_NONE);
 
 
 	clif_updatestatus(sd,SP_STATUSPOINT);
 	clif_updatestatus(sd,SP_STATUSPOINT);
 	clif_updatestatus(sd,SP_BASELEVEL);
 	clif_updatestatus(sd,SP_BASELEVEL);
 	clif_updatestatus(sd,SP_BASEEXP);
 	clif_updatestatus(sd,SP_BASEEXP);
 	clif_updatestatus(sd,SP_NEXTBASEEXP);
 	clif_updatestatus(sd,SP_NEXTBASEEXP);
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_FORCE);
 	status_percent_heal(&sd->bl,100,100);
 	status_percent_heal(&sd->bl,100,100);
 
 
 	if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
 	if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
@@ -5999,7 +6002,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
 	clif_updatestatus(sd,SP_JOBEXP);
 	clif_updatestatus(sd,SP_JOBEXP);
 	clif_updatestatus(sd,SP_NEXTJOBEXP);
 	clif_updatestatus(sd,SP_NEXTJOBEXP);
 	clif_updatestatus(sd,SP_SKILLPOINT);
 	clif_updatestatus(sd,SP_SKILLPOINT);
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_FORCE);
 	clif_misceffect(&sd->bl,1);
 	clif_misceffect(&sd->bl,1);
 	if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
 	if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd))
 		clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
 		clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
@@ -6336,7 +6339,7 @@ bool pc_statusup(struct map_session_data* sd, int type, int increase)
 	final_value = pc_setstat(sd, type, current + increase);
 	final_value = pc_setstat(sd, type, current + increase);
 	sd->status.status_point -= needed_points;
 	sd->status.status_point -= needed_points;
 
 
-	status_calc_pc(sd, 0);
+	status_calc_pc(sd,SCO_NONE);
 
 
 	// update increase cost indicator
 	// update increase cost indicator
 	clif_updatestatus(sd, SP_USTR + type-SP_STR);
 	clif_updatestatus(sd, SP_USTR + type-SP_STR);
@@ -6380,7 +6383,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
 
 
 	val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max));
 	val = pc_setstat(sd, type, cap_value(pc_getstat(sd,type) + val, 1, max));
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 
 
 	// update increase cost indicator
 	// update increase cost indicator
 	if( need != pc_need_status_point(sd,type,1) )
 	if( need != pc_need_status_point(sd,type,1) )
@@ -6426,7 +6429,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id)
 		sd->status.skill[skill_id].lv++;
 		sd->status.skill[skill_id].lv++;
 		sd->status.skill_point--;
 		sd->status.skill_point--;
 		if( !skill_get_inf(skill_id) )
 		if( !skill_get_inf(skill_id) )
-			status_calc_pc(sd,0); // Only recalculate for passive skills.
+			status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
 		else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
 		else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) )
 			pc_calc_skilltree(sd); // Required to grant all TK Ranker skills.
 			pc_calc_skilltree(sd); // Required to grant all TK Ranker skills.
 		else
 		else
@@ -6494,7 +6497,7 @@ int pc_allskillup(struct map_session_data *sd)
 			sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_);	// celest
 			sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_);	// celest
 		}
 		}
 	}
 	}
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 	//Required because if you could level up all skills previously,
 	//Required because if you could level up all skills previously,
 	//the update will not be sent as only the lv variable changes.
 	//the update will not be sent as only the lv variable changes.
 	clif_skillinfoblock(sd);
 	clif_skillinfoblock(sd);
@@ -6584,7 +6587,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
 	if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
 	if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
 		party_send_levelup(sd);
 		party_send_levelup(sd);
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd, SCO_FORCE);
 	clif_skillinfoblock(sd);
 	clif_skillinfoblock(sd);
 
 
 	return 0;
 	return 0;
@@ -6649,7 +6652,7 @@ int pc_resetstate(struct map_session_data* sd)
 		pc_setglobalreg(sd,"TK_MISSION_ID", 0);
 		pc_setglobalreg(sd,"TK_MISSION_ID", 0);
 	}
 	}
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd, SCO_NONE);
 
 
 	return 1;
 	return 1;
 }
 }
@@ -6760,11 +6763,10 @@ int pc_resetskill(struct map_session_data* sd, int flag)
 
 
 	sd->status.skill_point += skill_point;
 	sd->status.skill_point += skill_point;
 
 
-	if( flag&1 )
-	{
+	if (flag&1) {
 		clif_updatestatus(sd,SP_SKILLPOINT);
 		clif_updatestatus(sd,SP_SKILLPOINT);
 		clif_skillinfoblock(sd);
 		clif_skillinfoblock(sd);
-		status_calc_pc(sd,0);
+		status_calc_pc(sd, SCO_FORCE);
 	}
 	}
 
 
 	return skill_point;
 	return skill_point;
@@ -7053,7 +7055,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			) { 	// monster level up [Valaris]
 			) { 	// monster level up [Valaris]
 				clif_misceffect(&md->bl,0);
 				clif_misceffect(&md->bl,0);
 				md->level++;
 				md->level++;
-				status_calc_mob(md, 0);
+				status_calc_mob(md, SCO_NONE);
 				status_percent_heal(src,10,0);
 				status_percent_heal(src,10,0);
 
 
 				if( battle_config.show_mob_info&4 )
 				if( battle_config.show_mob_info&4 )
@@ -7450,11 +7452,9 @@ bool pc_setparam(struct map_session_data *sd,int type,int val)
 		clif_updatestatus(sd, SP_NEXTBASEEXP);
 		clif_updatestatus(sd, SP_NEXTBASEEXP);
 		clif_updatestatus(sd, SP_STATUSPOINT);
 		clif_updatestatus(sd, SP_STATUSPOINT);
 		clif_updatestatus(sd, SP_BASEEXP);
 		clif_updatestatus(sd, SP_BASEEXP);
-		status_calc_pc(sd, 0);
+		status_calc_pc(sd, SCO_NONE);
 		if(sd->status.party_id)
 		if(sd->status.party_id)
-		{
 			party_send_levelup(sd);
 			party_send_levelup(sd);
-		}
 		break;
 		break;
 	case SP_JOBLEVEL:
 	case SP_JOBLEVEL:
 		if ((unsigned int)val >= sd->status.job_level) {
 		if ((unsigned int)val >= sd->status.job_level) {
@@ -7900,7 +7900,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 	if(sd->status.manner < 0)
 	if(sd->status.manner < 0)
 		clif_changestatus(sd,SP_MANNER,sd->status.manner);
 		clif_changestatus(sd,SP_MANNER,sd->status.manner);
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_FORCE);
 	pc_checkallowskill(sd);
 	pc_checkallowskill(sd);
 	pc_equiplookall(sd);
 	pc_equiplookall(sd);
 
 
@@ -8012,12 +8012,12 @@ void pc_setoption(struct map_session_data *sd,int type)
 	if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
 	if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
 	{ // Mounting
 	{ // Mounting
 		clif_status_load(&sd->bl,SI_RIDING,1);
 		clif_status_load(&sd->bl,SI_RIDING,1);
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 	}
 	}
 	else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
 	else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) )
 	{ // Dismount
 	{ // Dismount
 		clif_status_load(&sd->bl,SI_RIDING,0);
 		clif_status_load(&sd->bl,SI_RIDING,0);
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 	}
 	}
 
 
 #ifndef NEW_CARTS
 #ifndef NEW_CARTS
@@ -8025,7 +8025,7 @@ void pc_setoption(struct map_session_data *sd,int type)
 		clif_cartlist(sd);
 		clif_cartlist(sd);
 		clif_updatestatus(sd, SP_CARTINFO);
 		clif_updatestatus(sd, SP_CARTINFO);
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
-			status_calc_pc(sd,0); //Apply speed penalty.
+			status_calc_pc(sd,SCO_NONE); //Apply speed penalty.
 	} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
 	} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
 		clif_clearcart(sd->fd);
 		clif_clearcart(sd->fd);
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
 		if(pc_checkskill(sd, MC_PUSHCART) < 10)
@@ -8041,15 +8041,15 @@ void pc_setoption(struct map_session_data *sd,int type)
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
 		if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
 		if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
 			clif_status_load(&sd->bl,SI_WUGRIDER,1);
 			clif_status_load(&sd->bl,SI_WUGRIDER,1);
-			status_calc_pc(sd,0);
+			status_calc_pc(sd,SCO_NONE);
 		} else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
 		} else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
 			clif_status_load(&sd->bl,SI_WUGRIDER,0);
 			clif_status_load(&sd->bl,SI_WUGRIDER,0);
-			status_calc_pc(sd,0);
+			status_calc_pc(sd,SCO_NONE);
 		}
 		}
 	}
 	}
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
 		if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) {
 		if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) {
-			status_calc_pc(sd, 0);
+			status_calc_pc(sd,SCO_NONE);
 			status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER);
@@ -8058,7 +8058,7 @@ void pc_setoption(struct map_session_data *sd,int type)
 			status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER);
 		} else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) {
 		} else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) {
-			status_calc_pc(sd, 0);
+			status_calc_pc(sd,SCO_NONE);
 			status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER);
 			status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER);
@@ -8124,7 +8124,7 @@ bool pc_setcart(struct map_session_data *sd,int type) {
 	}
 	}
 
 
 	if(pc_checkskill(sd, MC_PUSHCART) < 10)
 	if(pc_checkskill(sd, MC_PUSHCART) < 10)
-		status_calc_pc(sd,0); //Recalc speed penalty.
+		status_calc_pc(sd,SCO_NONE); //Recalc speed penalty.
 #else
 #else
 	// Update option
 	// Update option
 	option = sd->sc.option;
 	option = sd->sc.option;
@@ -8368,15 +8368,12 @@ bool pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type
 	switch( type )
 	switch( type )
 	{
 	{
 	case 3: //Char reg
 	case 3: //Char reg
-		if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val )
-		{
+		if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val ) {
 			i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
 			i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
 			sd->die_counter = val;
 			sd->die_counter = val;
 			if( i )
 			if( i )
-				status_calc_pc(sd,0); // Lost the bonus.
-		}
-		else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val )
-		{
+				status_calc_pc(sd,SCO_NONE); // Lost the bonus.
+		} else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val ) {
 			val = cap_value(val, 0, 1999);
 			val = cap_value(val, 0, 1999);
 			sd->cook_mastery = val;
 			sd->cook_mastery = val;
 		}
 		}
@@ -8385,13 +8382,10 @@ bool pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type
 		regmax = GLOBAL_REG_NUM;
 		regmax = GLOBAL_REG_NUM;
 	break;
 	break;
 	case 2: //Account reg
 	case 2: //Account reg
-		if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val )
-		{
+		if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val ) {
 			val = cap_value(val, 0, MAX_ZENY);
 			val = cap_value(val, 0, MAX_ZENY);
 			sd->cashPoints = val;
 			sd->cashPoints = val;
-		}
-		else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val )
-		{
+		} else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val ) {
 			val = cap_value(val, 0, MAX_ZENY);
 			val = cap_value(val, 0, MAX_ZENY);
 			sd->kafraPoints = val;
 			sd->kafraPoints = val;
 		}
 		}
@@ -8995,7 +8989,7 @@ bool pc_equipitem(struct map_session_data *sd,int n,int req_pos)
 		}
 		}
 	}
 	}
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 	if (flag) //Update skill data
 	if (flag) //Update skill data
 		clif_skillinfoblock(sd);
 		clif_skillinfoblock(sd);
 
 
@@ -9169,7 +9163,7 @@ bool pc_unequipitem(struct map_session_data *sd,int n,int flag) {
 
 
 	if(flag&1 || status_cacl) {
 	if(flag&1 || status_cacl) {
 		pc_checkallowskill(sd);
 		pc_checkallowskill(sd);
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 	}
 	}
 
 
 	if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele))
 	if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele))
@@ -9235,10 +9229,8 @@ void pc_checkitem(struct map_session_data *sd) {
 
 
 	if( calc_flag && sd->state.active ) {
 	if( calc_flag && sd->state.active ) {
 		pc_checkallowskill(sd);
 		pc_checkallowskill(sd);
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 	}
 	}
-
-	return;
 }
 }
 
 
 /*==========================================
 /*==========================================
@@ -9536,7 +9528,7 @@ void pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
 }
 }
 
 
 /*==========================================
 /*==========================================
- * Save 1 player data  at autosave intervalle
+ * Save 1 player data at autosave interval
  *------------------------------------------*/
  *------------------------------------------*/
 static int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
 static int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
 {
 {
@@ -10671,7 +10663,7 @@ int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) {
 	}
 	}
 
 
 	pc_bonus_script_remove(sd,i);
 	pc_bonus_script_remove(sd,i);
-	status_calc_pc(sd,false);
+	status_calc_pc(sd,SCO_NONE);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -10718,7 +10710,7 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) {
 		}
 		}
 	}
 	}
 	if (count && !(flag&BONUS_FLAG_REM_ON_LOGOUT)) //Don't need to do this if log out
 	if (count && !(flag&BONUS_FLAG_REM_ON_LOGOUT)) //Don't need to do this if log out
-		status_calc_pc(sd,false);
+		status_calc_pc(sd,SCO_NONE);
 }
 }
 
 
 /** [Cydh]
 /** [Cydh]

+ 3 - 0
src/map/pc.h

@@ -207,6 +207,7 @@ struct map_session_data {
 		unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
 		unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not.
 		unsigned int warping : 1;//states whether you're in the middle of a warp processing
 		unsigned int warping : 1;//states whether you're in the middle of a warp processing
 		unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc().
 		unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc().
+		unsigned int hold_recalc : 1;
 		unsigned int banking : 1; //1 when we using the banking system 0 when closed
 		unsigned int banking : 1; //1 when we using the banking system 0 when closed
 		unsigned int hpmeter_visible : 1;
 		unsigned int hpmeter_visible : 1;
 		bool disable_atcommand_on_npc; //Prevent to use atcommand while talking with NPC [Kichi]
 		bool disable_atcommand_on_npc; //Prevent to use atcommand while talking with NPC [Kichi]
@@ -565,6 +566,8 @@ struct map_session_data {
 	struct sc_display_entry **sc_display;
 	struct sc_display_entry **sc_display;
 	unsigned char sc_display_count;
 	unsigned char sc_display_count;
 
 
+	unsigned char delayed_damage; //[Ind]
+
 	// temporary debugging of bug #3504
 	// temporary debugging of bug #3504
 	const char* delunit_prevfile;
 	const char* delunit_prevfile;
 	int delunit_prevline;
 	int delunit_prevline;

+ 30 - 33
src/map/pet.c

@@ -68,7 +68,7 @@ void pet_set_intimate(struct pet_data *pd, int value)
 
 
 	pd->pet.intimate = value;
 	pd->pet.intimate = value;
 	if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
 	if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) )
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 }
 }
 
 
 int pet_create_egg(struct map_session_data *sd, int item_id)
 int pet_create_egg(struct map_session_data *sd, int item_id)
@@ -225,7 +225,7 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data)
 			pd->pet.intimate = 0;
 			pd->pet.intimate = 0;
 			pd->status.speed = pd->db->status.speed;
 			pd->status.speed = pd->db->status.speed;
 		}
 		}
-		status_calc_pet(pd, 0);
+		status_calc_pet(pd,SCO_NONE);
 		clif_send_petdata(sd,pd,1,pd->pet.intimate);
 		clif_send_petdata(sd,pd,1,pd->pet.intimate);
 	}
 	}
 	clif_send_petdata(sd,pd,2,pd->pet.hungry);
 	clif_send_petdata(sd,pd,2,pd->pet.hungry);
@@ -310,7 +310,7 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd)
 	pd->pet.incuvate = 1;
 	pd->pet.incuvate = 1;
 	unit_free(&pd->bl,CLR_OUTSIGHT);
 	unit_free(&pd->bl,CLR_OUTSIGHT);
 
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd,SCO_NONE);
 	sd->status.pet_id = 0;
 	sd->status.pet_id = 0;
 
 
 	return 1;
 	return 1;
@@ -366,19 +366,24 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet)
 	pd->bl.y = pd->ud.to_y;
 	pd->bl.y = pd->ud.to_y;
 
 
 	map_addiddb(&pd->bl);
 	map_addiddb(&pd->bl);
-	status_calc_pet(pd,1);
+	status_calc_pet(pd,SCO_FIRST);
 
 
 	pd->last_thinktime = gettick();
 	pd->last_thinktime = gettick();
 	pd->state.skillbonus = 0;
 	pd->state.skillbonus = 0;
+
 	if( battle_config.pet_status_support )
 	if( battle_config.pet_status_support )
 		run_script(pet_db[i].pet_script,0,sd->bl.id,0);
 		run_script(pet_db[i].pet_script,0,sd->bl.id,0);
-	if( pd->petDB && pd->petDB->equip_script )
-		status_calc_pc(sd,0);
 
 
-	if( battle_config.pet_hungry_delay_rate != 100 )
-		interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100;
-	else
-		interval = pd->petDB->hungry_delay;
+	if( pd->petDB ) {
+		if( pd->petDB->equip_script )
+			status_calc_pc(sd,SCO_NONE);
+
+		if( battle_config.pet_hungry_delay_rate != 100 )
+			interval = pd->petDB->hungry_delay * battle_config.pet_hungry_delay_rate / 100;
+		else
+			interval = pd->petDB->hungry_delay;
+	}
+
 	if( interval <= 0 )
 	if( interval <= 0 )
 		interval = 1;
 		interval = 1;
 	pd->pet_hungry_timer = add_timer(gettick() + interval, pet_hungry, sd->bl.id, 0);
 	pd->pet_hungry_timer = add_timer(gettick() + interval, pet_hungry, sd->bl.id, 0);
@@ -717,23 +722,19 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd)
 		clif_additem(sd,0,0,flag);
 		clif_additem(sd,0,0,flag);
 		map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
 		map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
 	}
 	}
-	if( battle_config.pet_equip_required )
-	{ // Skotlex: halt support timers if needed
-		if( pd->state.skillbonus )
-		{
+	if( battle_config.pet_equip_required ) { // Skotlex: halt support timers if needed
+		if( pd->state.skillbonus ) {
 			pd->state.skillbonus = 0;
 			pd->state.skillbonus = 0;
-			status_calc_pc(sd,0);
+			status_calc_pc(sd,SCO_NONE);
 		}
 		}
-		if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
-		{
+		if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER ) {
 			if( pd->s_skill->id )
 			if( pd->s_skill->id )
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
 				delete_timer(pd->s_skill->timer, pet_skill_support_timer);
 			else
 			else
 				delete_timer(pd->s_skill->timer, pet_heal_timer);
 				delete_timer(pd->s_skill->timer, pet_heal_timer);
 			pd->s_skill->timer = INVALID_TIMER;
 			pd->s_skill->timer = INVALID_TIMER;
 		}
 		}
-		if( pd->bonus && pd->bonus->timer != INVALID_TIMER )
-		{
+		if( pd->bonus && pd->bonus->timer != INVALID_TIMER ) {
 			delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 			delete_timer(pd->bonus->timer, pet_skill_bonus_timer);
 			pd->bonus->timer = INVALID_TIMER;
 			pd->bonus->timer = INVALID_TIMER;
 		}
 		}
@@ -746,9 +747,9 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
 {
 {
 	int i,k;
 	int i,k;
 
 
-	k=pd->petDB->FoodID;
-	i=pc_search_inventory(sd,k);
-	if(i < 0) {
+	k = pd->petDB->FoodID;
+	i = pc_search_inventory(sd,k);
+	if( i < 0 ) {
 		clif_pet_food(sd,k,0);
 		clif_pet_food(sd,k,0);
 		return 1;
 		return 1;
 	}
 	}
@@ -756,29 +757,25 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd)
 
 
 	if( pd->pet.hungry > 90 )
 	if( pd->pet.hungry > 90 )
 		pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
 		pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full);
-	else
-	{
+	else {
 		if( battle_config.pet_friendly_rate != 100 )
 		if( battle_config.pet_friendly_rate != 100 )
-			k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100;
+			k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate) / 100;
 		else
 		else
 			k = pd->petDB->r_hungry;
 			k = pd->petDB->r_hungry;
-		if( pd->pet.hungry > 75 )
-		{
+		if( pd->pet.hungry > 75 ) {
 			k = k >> 1;
 			k = k >> 1;
 			if( k <= 0 )
 			if( k <= 0 )
 				k = 1;
 				k = 1;
 		}
 		}
 		pet_set_intimate(pd, pd->pet.intimate + k);
 		pet_set_intimate(pd, pd->pet.intimate + k);
 	}
 	}
-	if( pd->pet.intimate <= 0 )
-	{
+	if( pd->pet.intimate <= 0 ) {
 		pd->pet.intimate = 0;
 		pd->pet.intimate = 0;
 		pet_stop_attack(pd);
 		pet_stop_attack(pd);
 		pd->status.speed = pd->db->status.speed;
 		pd->status.speed = pd->db->status.speed;
-	}
-	else if( pd->pet.intimate > 1000 )
+	} else if( pd->pet.intimate > 1000 )
 		pd->pet.intimate = 1000;
 		pd->pet.intimate = 1000;
-	status_calc_pet(pd, 0);
+	status_calc_pet(pd,SCO_NONE);
 	pd->pet.hungry += pd->petDB->fullness;
 	pd->pet.hungry += pd->petDB->fullness;
 	if( pd->pet.hungry > 100 )
 	if( pd->pet.hungry > 100 )
 		pd->pet.hungry = 100;
 		pd->pet.hungry = 100;
@@ -1087,7 +1084,7 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 
 	if (pd->state.skillbonus != bonus) {
 	if (pd->state.skillbonus != bonus) {
 		pd->state.skillbonus = bonus;
 		pd->state.skillbonus = bonus;
-		status_calc_pc(sd, 0);
+		status_calc_pc(sd,SCO_NONE);
 	}
 	}
 	// wait for the next timer
 	// wait for the next timer
 	pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0);
 	pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0);

+ 41 - 42
src/map/script.c

@@ -10998,7 +10998,6 @@ static void script_detach_rid(struct script_state* st)
 	}
 	}
 }
 }
 
 
-
 /*=========================================================================
 /*=========================================================================
  * Attaches a set of RIDs to the current script. [digitalhamster]
  * Attaches a set of RIDs to the current script. [digitalhamster]
  * addrid(<type>{,<flag>{,<parameters>}});
  * addrid(<type>{,<flag>{,<parameters>}});
@@ -11016,17 +11015,17 @@ static void script_detach_rid(struct script_state* st)
  *	0 : Players are always attached. (default)
  *	0 : Players are always attached. (default)
  *	1 : Players currently running another script will not be attached.
  *	1 : Players currently running another script will not be attached.
  *-------------------------------------------------------------------------*/
  *-------------------------------------------------------------------------*/
-
 static int buildin_addrid_sub(struct block_list *bl,va_list ap)
 static int buildin_addrid_sub(struct block_list *bl,va_list ap)
 {
 {
 	int forceflag;
 	int forceflag;
 	struct map_session_data *sd = (TBL_PC *)bl;
 	struct map_session_data *sd = (TBL_PC *)bl;
 	struct script_state* st;
 	struct script_state* st;
 
 
-	st=va_arg(ap,struct script_state*);
-	forceflag=va_arg(ap,int);
-	if(!forceflag||!sd->st)
-		if(sd->status.account_id!=st->rid)
+	st = va_arg(ap,struct script_state*);
+	forceflag = va_arg(ap,int);
+
+	if(!forceflag || !sd->st)
+		if(sd->status.account_id != st->rid)
 			run_script(st->script,st->pos,sd->status.account_id,st->oid);
 			run_script(st->script,st->pos,sd->status.account_id,st->oid);
 	return 0;
 	return 0;
 }
 }
@@ -11036,46 +11035,48 @@ BUILDIN_FUNC(addrid)
 	struct s_mapiterator* iter;
 	struct s_mapiterator* iter;
 	struct block_list *bl;
 	struct block_list *bl;
 	TBL_PC *sd;
 	TBL_PC *sd;
-	if(st->rid<1){
+
+	if(st->rid < 1) {
 		st->state = END;
 		st->state = END;
-		bl=map_id2bl(st->oid);
+		bl = map_id2bl(st->oid);
 	} else
 	} else
-		bl=map_id2bl(st->rid); //if run without rid it'd error,also oid if npc, else rid for map
+		bl = map_id2bl(st->rid); //if run without rid it'd error,also oid if npc, else rid for map
 	iter = mapit_getallusers();
 	iter = mapit_getallusers();
-	switch(script_getnum(st,2)){
+
+	switch(script_getnum(st,2)) {
 		case 0:
 		case 0:
-			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
-				if(!script_getnum(st,3)||!sd->st)
-					if(sd->status.account_id!=st->rid) //attached player already runs.
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) {
+				if(!script_getnum(st,3) || !sd->st)
+					if(sd->status.account_id != st->rid) //attached player already runs.
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 			}
 			}
 			break;
 			break;
 		case 1:
 		case 1:
-			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
-				if(!script_getnum(st,3)||!sd->st)
-					if((sd->bl.m == bl->m)&&(sd->status.account_id!=st->rid))
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) {
+				if(!script_getnum(st,3) || !sd->st)
+					if((sd->bl.m == bl->m) && (sd->status.account_id != st->rid))
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 			}
 			}
 			break;
 			break;
 		case 2:
 		case 2:
-			if(script_getnum(st,4)==0){
+			if(script_getnum(st,4) == 0) {
 				script_pushint(st,0);
 				script_pushint(st,0);
 				return 0;
 				return 0;
 			}
 			}
-			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
-				if(!script_getnum(st,3)||!sd->st)
-					if((sd->status.account_id!=st->rid)&&(sd->status.party_id==script_getnum(st,4))) //attached player already runs.
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) {
+				if(!script_getnum(st,3) || !sd->st)
+					if((sd->status.account_id != st->rid) && (sd->status.party_id == script_getnum(st,4))) //attached player already runs.
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 			}
 			}
 			break;
 			break;
 		case 3:
 		case 3:
-			if(script_getnum(st,4)==0){
+			if(script_getnum(st,4) == 0) {
 				script_pushint(st,0);
 				script_pushint(st,0);
 				return 0;
 				return 0;
 			}
 			}
-			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){
-				if(!script_getnum(st,3)||!sd->st)
-					if((sd->status.account_id!=st->rid)&&(sd->status.guild_id==script_getnum(st,4))) //attached player already runs.
+			for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) {
+				if(!script_getnum(st,3) || !sd->st)
+					if((sd->status.account_id != st->rid) && (sd->status.guild_id == script_getnum(st,4))) //attached player already runs.
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 						run_script(st->script,st->pos,sd->status.account_id,st->oid);
 			}
 			}
 			break;
 			break;
@@ -11085,11 +11086,11 @@ BUILDIN_FUNC(addrid)
 			st,script_getnum(st,3));//4-x0 , 5-y0 , 6-x1, 7-y1
 			st,script_getnum(st,3));//4-x0 , 5-y0 , 6-x1, 7-y1
 			break;
 			break;
 		default:
 		default:
-			if((map_id2sd(script_getnum(st,2)))==NULL){ // Player not found.
+			if((map_id2sd(script_getnum(st,2))) == NULL) { // Player not found.
 				script_pushint(st,0);
 				script_pushint(st,0);
 				return 0;
 				return 0;
 			}
 			}
-			if(!script_getnum(st,3)||!map_id2sd(script_getnum(st,2))->st) {
+			if(!script_getnum(st,3) || !map_id2sd(script_getnum(st,2))->st) {
 				run_script(st->script,st->pos,script_getnum(st,2),st->oid);
 				run_script(st->script,st->pos,script_getnum(st,2),st->oid);
 				script_pushint(st,1);
 				script_pushint(st,1);
 			}
 			}
@@ -13170,11 +13171,11 @@ BUILDIN_FUNC(nude)
 	}
 	}
 
 
 	if( calcflag )
 	if( calcflag )
-		status_calc_pc(sd,0);
+		status_calc_pc(sd,SCO_NONE);
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
-int atcommand_sub(struct script_state* st,int type){
+int atcommand_sub(struct script_state* st,int type) {
 	TBL_PC dummy_sd;
 	TBL_PC dummy_sd;
 	TBL_PC* sd;
 	TBL_PC* sd;
 	int fd;
 	int fd;
@@ -13627,11 +13628,10 @@ BUILDIN_FUNC(npcwalkto)
 	y=script_getnum(st,3);
 	y=script_getnum(st,3);
 
 
 	if(nd) {
 	if(nd) {
-		if (!nd->status.hp) {
-			status_calc_npc(nd, true);
-		} else {
-			status_calc_npc(nd, false);
-		}
+		if (!nd->status.hp)
+			status_calc_npc(nd, SCO_FIRST);
+		else
+			status_calc_npc(nd, SCO_NONE);
 		unit_walktoxy(&nd->bl,x,y,0);
 		unit_walktoxy(&nd->bl,x,y,0);
 	}
 	}
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
@@ -18123,17 +18123,16 @@ BUILDIN_FUNC(npcskill)
 	nd->level = npc_level;
 	nd->level = npc_level;
 	nd->stat_point = stat_point;
 	nd->stat_point = stat_point;
 
 
-	if (!nd->status.hp) {
-		status_calc_npc(nd, true);
-	} else {
-		status_calc_npc(nd, false);
-	}
+	if (!nd->status.hp)
+		status_calc_npc(nd, SCO_FIRST);
+	else
+		status_calc_npc(nd, SCO_NONE);
 
 
-	if (skill_get_inf(skill_id)&INF_GROUND_SKILL) {
+	if (skill_get_inf(skill_id)&INF_GROUND_SKILL)
 		unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level);
 		unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level);
-	} else {
+	else
 		unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level);
 		unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level);
-	}
+
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 
@@ -18723,7 +18722,7 @@ BUILDIN_FUNC(bonus_script) {
 	if (sd->bonus_script[i].icon != SI_BLANK) //Gives status icon if exist
 	if (sd->bonus_script[i].icon != SI_BLANK) //Gives status icon if exist
 		clif_status_change(&sd->bl,sd->bonus_script[i].icon,1,dur,1,0,0);
 		clif_status_change(&sd->bl,sd->bonus_script[i].icon,1,dur,1,0,0);
 
 
-	status_calc_pc(sd,false);
+	status_calc_pc(sd,SCO_NONE);
 	return SCRIPT_CMD_SUCCESS;
 	return SCRIPT_CMD_SUCCESS;
 }
 }
 
 

+ 60 - 47
src/map/status.c

@@ -2282,17 +2282,17 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev
 /** [Skotlex]
 /** [Skotlex]
 * Calculates the initial status for the given mob
 * Calculates the initial status for the given mob
 * @param md: Mob object
 * @param md: Mob object
-* @param first: Whether or not it is the first calculation
+* @param opt: Whether or not it is the first calculation
 		This will only be false when a mob levels up (Regular and WoE Guardians)
 		This will only be false when a mob levels up (Regular and WoE Guardians)
 * @return 1 for calculated special statuses or 0 for none
 * @return 1 for calculated special statuses or 0 for none
 **/
 **/
-int status_calc_mob_(struct mob_data* md, bool first)
+int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt)
 {
 {
 	struct status_data *status;
 	struct status_data *status;
 	struct block_list *mbl = NULL;
 	struct block_list *mbl = NULL;
 	int flag=0;
 	int flag=0;
 
 
-	if(first) { // Set basic level on respawn.
+	if (opt&SCO_FIRST) { // Set basic level on respawn.
 		if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
 		if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
 			;
 			;
 		else
 		else
@@ -2322,7 +2322,7 @@ int status_calc_mob_(struct mob_data* md, bool first)
 			aFree(md->base_status);
 			aFree(md->base_status);
 			md->base_status = NULL;
 			md->base_status = NULL;
 		}
 		}
-		if(first)
+		if (opt&SCO_FIRST)
 			memcpy(&md->status, &md->db->status, sizeof(struct status_data));
 			memcpy(&md->status, &md->db->status, sizeof(struct status_data));
 		return 0;
 		return 0;
 	}
 	}
@@ -2476,7 +2476,7 @@ int status_calc_mob_(struct mob_data* md, bool first)
 		}
 		}
 	}
 	}
 
 
-	if( first ) // Initial battle status
+	if (opt&SCO_FIRST) // Initial battle status
 		memcpy(&md->status, status, sizeof(struct status_data));
 		memcpy(&md->status, status, sizeof(struct status_data));
 
 
 	return 1;
 	return 1;
@@ -2485,15 +2485,15 @@ int status_calc_mob_(struct mob_data* md, bool first)
 /** [Skotlex]
 /** [Skotlex]
 * Calculates the stats of the given pet
 * Calculates the stats of the given pet
 * @param pd: Pet object
 * @param pd: Pet object
-* @param first: Whether or not it is the first calculation
+* @param opt: Whether or not it is the first calculation
 		This will only be false when a pet levels up
 		This will only be false when a pet levels up
 * @return 1
 * @return 1
 **/
 **/
-int status_calc_pet_(struct pet_data *pd, bool first)
+int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
 {
 {
 	nullpo_ret(pd);
 	nullpo_ret(pd);
 
 
-	if (first) {
+	if (opt&SCO_FIRST) {
 		memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
 		memcpy(&pd->status, &pd->db->status, sizeof(struct status_data));
 		pd->status.mode = MD_CANMOVE; // Pets discard all modes, except walking
 		pd->status.mode = MD_CANMOVE; // Pets discard all modes, except walking
 		pd->status.class_ = CLASS_NORMAL;
 		pd->status.class_ = CLASS_NORMAL;
@@ -2512,10 +2512,11 @@ int status_calc_pet_(struct pet_data *pd, bool first)
 		lv =sd->status.base_level*battle_config.pet_lv_rate/100;
 		lv =sd->status.base_level*battle_config.pet_lv_rate/100;
 		if (lv < 0)
 		if (lv < 0)
 			lv = 1;
 			lv = 1;
-		if (lv != pd->pet.level || first) {
+		if (lv != pd->pet.level || opt&SCO_FIRST) {
 			struct status_data *bstat = &pd->db->status, *status = &pd->status;
 			struct status_data *bstat = &pd->db->status, *status = &pd->status;
+
 			pd->pet.level = lv;
 			pd->pet.level = lv;
-			if (!first) // Lv Up animation
+			if (!(opt&SCO_FIRST)) // Lv Up animation
 				clif_misceffect(&pd->bl, 0);
 				clif_misceffect(&pd->bl, 0);
 			status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
 			status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv;
 			status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
 			status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv;
@@ -2537,10 +2538,10 @@ int status_calc_pet_(struct pet_data *pd, bool first)
 
 
 			status_calc_misc(&pd->bl, &pd->status, lv);
 			status_calc_misc(&pd->bl, &pd->status, lv);
 
 
-			if (!first) // Not done the first time because the pet is not visible yet
+			if (!(opt&SCO_FIRST)) // Not done the first time because the pet is not visible yet
 				clif_send_petstatus(sd);
 				clif_send_petstatus(sd);
 		}
 		}
-	} else if (first) {
+	} else if (opt&SCO_FIRST) {
 		status_calc_misc(&pd->bl, &pd->status, pd->db->lv);
 		status_calc_misc(&pd->bl, &pd->status, pd->db->lv);
 		if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv)
 		if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv)
 			pd->pet.level = pd->db->lv;
 			pd->pet.level = pd->db->lv;
@@ -2751,7 +2752,7 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned
 	uint16 idx, level, job_id;
 	uint16 idx, level, job_id;
 
 
 	nullpo_ret(sd);
 	nullpo_ret(sd);
-	
+
 	job_id = pc_mapid2jobid(sd->class_,sd->status.sex);
 	job_id = pc_mapid2jobid(sd->class_,sd->status.sex);
 	idx = pc_class2idx(job_id);
 	idx = pc_class2idx(job_id);
 	level = max(sd->status.base_level,1);
 	level = max(sd->status.base_level,1);
@@ -2774,10 +2775,10 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned
 * Calculates player data from scratch without counting SC adjustments
 * Calculates player data from scratch without counting SC adjustments
 * Should be invoked whenever players raise stats, learn passive skills or change equipment
 * Should be invoked whenever players raise stats, learn passive skills or change equipment
 * @param sd: Player object
 * @param sd: Player object
-* @param first: Whether it is first calc (login) or not
+* @param opt: Whether it is first calc (login) or not
 * @return (-1) for too many recursive calls, (1) recursive call, (0) success
 * @return (-1) for too many recursive calls, (1) recursive call, (0) success
 **/
 **/
-int status_calc_pc_(struct map_session_data* sd, bool first)
+int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
 {
 {
 	static int calculating = 0; ///< Check for recursive call preemption. [Skotlex]
 	static int calculating = 0; ///< Check for recursive call preemption. [Skotlex]
 	struct status_data *status; ///< Pointer to the player's base status
 	struct status_data *status; ///< Pointer to the player's base status
@@ -2799,7 +2800,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 
 
 	sd->max_weight = job_info[pc_class2idx(sd->status.class_)].max_weight_base+sd->status.str*300;
 	sd->max_weight = job_info[pc_class2idx(sd->status.class_)].max_weight_base+sd->status.str*300;
 
 
-	if(first) {
+	if (opt&SCO_FIRST) {
 		// Load Hp/SP from char-received data.
 		// Load Hp/SP from char-received data.
 		sd->battle_status.hp = sd->status.hp;
 		sd->battle_status.hp = sd->status.hp;
 		sd->battle_status.sp = sd->status.sp;
 		sd->battle_status.sp = sd->status.sp;
@@ -2961,7 +2962,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 		status->def += sd->inventory_data[index]->def;
 		status->def += sd->inventory_data[index]->def;
 
 
 		// Items may be equipped, their effects however are nullified.
 		// Items may be equipped, their effects however are nullified.
-		if(first && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT)
+		if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT)
 			|| !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { // Execute equip-script on login
 			|| !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { // Execute equip-script on login
 			run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
 			run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
 			if (!calculating)
 			if (!calculating)
@@ -3112,7 +3113,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 				data = itemdb_exists(c);
 				data = itemdb_exists(c);
 				if(!data)
 				if(!data)
 					continue;
 					continue;
-				if(first && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {// Execute equip-script on login
+				if (opt&SCO_FIRST && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {// Execute equip-script on login
 					run_script(data->equip_script,0,sd->bl.id,0);
 					run_script(data->equip_script,0,sd->bl.id,0);
 					if (!calculating)
 					if (!calculating)
 						return 1;
 						return 1;
@@ -3608,15 +3609,15 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 /**
 /**
 * Calculates Mercenary data
 * Calculates Mercenary data
 * @param md: Mercenary object
 * @param md: Mercenary object
-* @param first: Whether it is first calc or not (0 on level up or status)
+* @param opt: Whether it is first calc or not (0 on level up or status)
 * @return 0
 * @return 0
 **/
 **/
-int status_calc_mercenary_(struct mercenary_data *md, bool first)
+int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt)
 {
 {
 	struct status_data *status = &md->base_status;
 	struct status_data *status = &md->base_status;
 	struct s_mercenary *merc = &md->mercenary;
 	struct s_mercenary *merc = &md->mercenary;
 
 
-	if( first ) {
+	if (opt&SCO_FIRST) {
 		memcpy(status, &md->db->status, sizeof(struct status_data));
 		memcpy(status, &md->db->status, sizeof(struct status_data));
 		status->class_ = CLASS_NORMAL;
 		status->class_ = CLASS_NORMAL;
 		status->mode = MD_CANMOVE|MD_CANATTACK;
 		status->mode = MD_CANMOVE|MD_CANATTACK;
@@ -3637,10 +3638,10 @@ int status_calc_mercenary_(struct mercenary_data *md, bool first)
 /**
 /**
 * Calculates Homunculus data
 * Calculates Homunculus data
 * @param hd: Homunculus object
 * @param hd: Homunculus object
-* @param first: Whether it is first calc or not (0 on level up or status)
+* @param opt: Whether it is first calc or not (0 on level up or status)
 * @return 1
 * @return 1
 **/
 **/
-int status_calc_homunculus_(struct homun_data *hd, bool first)
+int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt)
 {
 {
 	struct status_data *status = &hd->base_status;
 	struct status_data *status = &hd->base_status;
 	struct s_homunculus *hom = &hd->homunculus;
 	struct s_homunculus *hom = &hd->homunculus;
@@ -3654,7 +3655,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first)
 	status->int_ = hom->int_ / 10;
 	status->int_ = hom->int_ / 10;
 	status->luk = hom->luk / 10;
 	status->luk = hom->luk / 10;
 
 
-	if (first) {
+	if (opt&SCO_FIRST) {
 		const struct s_homunculus_db *db = hd->homunculusDB;
 		const struct s_homunculus_db *db = hd->homunculusDB;
 		status->def_ele =  db->element;
 		status->def_ele =  db->element;
 		status->ele_lv = 1;
 		status->ele_lv = 1;
@@ -3710,7 +3711,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first)
 	if((skill = hom_checkskill(hd,HLIF_BRAIN)) > 0)
 	if((skill = hom_checkskill(hd,HLIF_BRAIN)) > 0)
 		status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ;
 		status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ;
 
 
-	if (first) {
+	if (opt&SCO_FIRST) {
 		hd->battle_status.hp = hom->hp ;
 		hd->battle_status.hp = hom->hp ;
 		hd->battle_status.sp = hom->sp ;
 		hd->battle_status.sp = hom->sp ;
 		if(hom->class_ == 6052) // Eleanor
 		if(hom->class_ == 6052) // Eleanor
@@ -3735,10 +3736,10 @@ int status_calc_homunculus_(struct homun_data *hd, bool first)
 /**
 /**
 * Calculates Elemental data
 * Calculates Elemental data
 * @param ed: Elemental object
 * @param ed: Elemental object
-* @param first: Whether it is first calc or not (0 on status change)
+* @param opt: Whether it is first calc or not (0 on status change)
 * @return 0
 * @return 0
 **/
 **/
-int status_calc_elemental_(struct elemental_data *ed, bool first)
+int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt)
 {
 {
 	struct status_data *status = &ed->base_status;
 	struct status_data *status = &ed->base_status;
 	struct s_elemental *ele = &ed->elemental;
 	struct s_elemental *ele = &ed->elemental;
@@ -3747,7 +3748,7 @@ int status_calc_elemental_(struct elemental_data *ed, bool first)
 	if( !sd )
 	if( !sd )
 		return 0;
 		return 0;
 
 
-	if( first ) {
+	if (opt&SCO_FIRST) {
 		memcpy(status, &ed->db->status, sizeof(struct status_data));
 		memcpy(status, &ed->db->status, sizeof(struct status_data));
 		if( !ele->mode )
 		if( !ele->mode )
 			status->mode = EL_MODE_PASSIVE;
 			status->mode = EL_MODE_PASSIVE;
@@ -3785,17 +3786,17 @@ int status_calc_elemental_(struct elemental_data *ed, bool first)
 /**
 /**
 * Calculates NPC data
 * Calculates NPC data
 * @param nd: NPC object
 * @param nd: NPC object
-* @param first: Whether it is first calc or not (what?)
+* @param opt: Whether it is first calc or not (what?)
 * @return 0
 * @return 0
 **/
 **/
-int status_calc_npc_(struct npc_data *nd, bool first)
+int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt)
 {
 {
 	struct status_data *status = &nd->status;
 	struct status_data *status = &nd->status;
 
 
 	if (!nd)
 	if (!nd)
 		return 0;
 		return 0;
 
 
-	if (first) {
+	if (opt&SCO_FIRST) {
 		status->hp = 1;
 		status->hp = 1;
 		status->sp = 1;
 		status->sp = 1;
 		status->max_hp = 1;
 		status->max_hp = 1;
@@ -4550,38 +4551,47 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 * See [set_sc] [add_sc]
 * See [set_sc] [add_sc]
 * @param bl: Object whose status has changed [PC|MOB|HOM|MER|ELEM]
 * @param bl: Object whose status has changed [PC|MOB|HOM|MER|ELEM]
 * @param flag: Which status has changed on bl
 * @param flag: Which status has changed on bl
-* @param first: If true, will cause status_calc_* functions to run their base status initialization code
+* @param opt: If true, will cause status_calc_* functions to run their base status initialization code
 **/
 **/
-void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first)
+void status_calc_bl_(struct block_list* bl, enum scb_flag flag, enum e_status_calc_opt opt)
 {
 {
 	struct status_data b_status; // Previous battle status
 	struct status_data b_status; // Previous battle status
 	struct status_data* status; // Pointer to current battle status
 	struct status_data* status; // Pointer to current battle status
 
 
+	if (bl->type == BL_PC && ((TBL_PC*)bl)->delayed_damage != 0) {
+		if (opt&SCO_FORCE)
+			((TBL_PC*)bl)->state.hold_recalc = 0; /* Clear and move on */
+		else {
+			((TBL_PC*)bl)->state.hold_recalc = 1; /* Flag and stop */
+			return;
+		}
+	}
+
 	// Remember previous values
 	// Remember previous values
 	status = status_get_status_data(bl);
 	status = status_get_status_data(bl);
 	memcpy(&b_status, status, sizeof(struct status_data));
 	memcpy(&b_status, status, sizeof(struct status_data));
 
 
 	if( flag&SCB_BASE ) { // Calculate the object's base status too
 	if( flag&SCB_BASE ) { // Calculate the object's base status too
 		switch( bl->type ) {
 		switch( bl->type ) {
-		case BL_PC:  status_calc_pc_(BL_CAST(BL_PC,bl), first);          break;
-		case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), first);        break;
-		case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), first);        break;
-		case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break;
-		case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first);  break;
-		case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first);  break;
-		case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), first); break;
+		case BL_PC:  status_calc_pc_(BL_CAST(BL_PC,bl), opt);          break;
+		case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), opt);        break;
+		case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), opt);        break;
+		case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), opt); break;
+		case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), opt);  break;
+		case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), opt);  break;
+		case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), opt); break;
 		}
 		}
 	}
 	}
 
 
-	if( first && bl->type == BL_MOB )
+	if (opt&SCO_FIRST && bl->type == BL_MOB)
 		return; // Assume there will be no statuses active
 		return; // Assume there will be no statuses active
-		
+
 	if( bl->type == BL_PET )
 	if( bl->type == BL_PET )
 		return; // Pets are not affected by statuses
 		return; // Pets are not affected by statuses
-	
+
 	status_calc_bl_main(bl, flag);
 	status_calc_bl_main(bl, flag);
-	
-	if( first && bl->type == BL_HOM )
+
+	if (opt&SCO_FIRST && bl->type == BL_HOM)
 		return; // Client update handled by caller
 		return; // Client update handled by caller
 
 
 	// Compare against new values and send client updates
 	// Compare against new values and send client updates
@@ -10192,8 +10202,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true);
 		status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true);
 
 
 
 
-	if(sd && sd->pd)
-		pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing
+	if(sd) {
+		if (sd->pd)
+			pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing
+		status_calc_pc(sd, SCO_NONE);
+	}
 
 
 	 // 1st thing to execute when loading status
 	 // 1st thing to execute when loading status
 	switch (type) {
 	switch (type) {

+ 23 - 16
src/map/status.h

@@ -1725,6 +1725,12 @@ enum scb_flag
 	SCB_ALL		= 0x3FFFFFFF
 	SCB_ALL		= 0x3FFFFFFF
 };
 };
 
 
+enum e_status_calc_opt {
+	SCO_NONE  = 0x0,
+	SCO_FIRST = 0x1, /* Trigger the calculations that should take place only onspawn/once */
+	SCO_FORCE = 0x2, /* Only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage */
+};
+
 ///Enum for bonus_script's flag
 ///Enum for bonus_script's flag
 enum e_bonus_script_flags {
 enum e_bonus_script_flags {
 	BONUS_FLAG_REM_ON_DEAD		= 0x01,	//Remove bonus when dead
 	BONUS_FLAG_REM_ON_DEAD		= 0x01,	//Remove bonus when dead
@@ -1992,22 +1998,23 @@ int status_change_timer_sub(struct block_list* bl, va_list ap);
 int status_change_clear(struct block_list* bl, int type);
 int status_change_clear(struct block_list* bl, int type);
 void status_change_clear_buffs(struct block_list* bl, int type);
 void status_change_clear_buffs(struct block_list* bl, int type);
 
 
-#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), false)
-#define status_calc_mob(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_pet(pd, first) status_calc_bl_(&(pd)->bl, SCB_ALL, first)
-#define status_calc_pc(sd, first) status_calc_bl_(&(sd)->bl, SCB_ALL, first)
-#define status_calc_homunculus(hd, first) status_calc_bl_(&(hd)->bl, SCB_ALL, first)
-#define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first)
-#define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first)
-#define status_calc_npc(nd, first) status_calc_bl_(&(nd)->bl, SCB_ALL, first)
-
-void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first);
-int status_calc_mob_(struct mob_data* md, bool first);
-int status_calc_pet_(struct pet_data* pd, bool first);
-int status_calc_pc_(struct map_session_data* sd, bool first);
-int status_calc_homunculus_(struct homun_data *hd, bool first);
-int status_calc_mercenary_(struct mercenary_data *md, bool first);
-int status_calc_elemental_(struct elemental_data *ed, bool first);
+#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), SCO_NONE)
+#define status_calc_mob(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt)
+#define status_calc_pet(pd, opt) status_calc_bl_(&(pd)->bl, SCB_ALL, opt)
+#define status_calc_pc(sd, opt) status_calc_bl_(&(sd)->bl, SCB_ALL, opt)
+#define status_calc_homunculus(hd, opt) status_calc_bl_(&(hd)->bl, SCB_ALL, opt)
+#define status_calc_mercenary(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt)
+#define status_calc_elemental(ed, opt) status_calc_bl_(&(ed)->bl, SCB_ALL, opt)
+#define status_calc_npc(nd, opt) status_calc_bl_(&(nd)->bl, SCB_ALL, opt)
+
+void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt);
+int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt);
+int status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt);
+int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt);
+int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt);
+int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt);
+int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt);
+int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt);
 
 
 void status_calc_misc(struct block_list *bl, struct status_data *status, int level);
 void status_calc_misc(struct block_list *bl, struct status_data *status, int level);
 void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);
 void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);