From c84d6f0062cefc26af7a4d55336bc06c68a15ac3 Mon Sep 17 00:00:00 2001
From: skotlex <skotlex@54d463be-8e91-2dee-dedb-b68131a5f0ec>
Date: Thu, 18 Jan 2007 19:30:22 +0000
Subject: - Modified the Storm Gust freeze counter code. It now takes into
 consideration the ID of the skill before increasing the counter, which should
 effectively yield the closest aproximation to official (even though the
 counter will reset if you step out of a SG and into another one, we do not
 know yet what should happen in such a case). - Added @homshuffle. It
 recalculates the homunculus stats, as if the homunc was sent back to level 1,
 and then releveled. This command is mean to help fix those previously created
 Homunculus that are much stronger than they should be.

git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@9671 54d463be-8e91-2dee-dedb-b68131a5f0ec
---
 Changelog-Trunk.txt             |  9 +++++++
 conf-tmpl/atcommand_athena.conf |  3 +++
 src/map/atcommand.c             | 52 +++++++++++++++++++++++++++++++++++++++++
 src/map/atcommand.h             |  1 +
 src/map/mercenary.c             | 20 ++++++++++++++++
 src/map/mercenary.h             |  1 +
 src/map/skill.c                 | 15 ++++++++++--
 src/map/status.c                |  8 +------
 8 files changed, 100 insertions(+), 9 deletions(-)

diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index be15728fa..2c5efe43b 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,15 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
 2007/01/18
+	* Modified the Storm Gust freeze counter code. It now takes into
+	  consideration the ID of the skill before increasing the counter, which
+	  should effectively yield the closest aproximation to official (even though
+	  the counter will reset if you step out of a SG and into another one, we do
+	  not know yet what should happen in such a case).
+	* Added @homshuffle. It recalculates the homunculus stats, as if the homunc
+	  was sent back to level 1, and then releveled. This command is mean to help
+	  fix those previously created Homunculus that are much stronger than they
+	  should be.
 	* Fixed overflow on the mob delay adjustment setting.
 	* Fixed characters being unable to trade again if you attempt a trade on
 	  someone who is on storage/npc when you accept the trade. [Skotlex]
diff --git a/conf-tmpl/atcommand_athena.conf b/conf-tmpl/atcommand_athena.conf
index 22f055668..1c184ed7e 100644
--- a/conf-tmpl/atcommand_athena.conf
+++ b/conf-tmpl/atcommand_athena.conf
@@ -618,6 +618,9 @@ makehomun: 60
 homfriendly: 60
 homhungry: 60
 
+//Re-calculates stats, as if the homun was sent back to level 1 and re-leveled
+homshuffle: 60
+
 //----------------------
 // 80: GM Chief commands
 
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index f5cacb8fa..95002473e 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -312,6 +312,7 @@ ACMD_FUNC(homhungry);	//[orn]
 ACMD_FUNC(homtalk);	//[orn]
 ACMD_FUNC(hominfo);	//[Toms]
 ACMD_FUNC(homstats);	//[Skotlex]
+ACMD_FUNC(homshuffle);	//[Skotlex]
 ACMD_FUNC(showmobs); //KarLaeda
 
 /*==========================================
@@ -644,6 +645,7 @@ static AtCommandInfo atcommand_info[] = {
 	{ AtCommand_HomTalk,			"@homtalk",		10, atcommand_homtalk },
 	{ AtCommand_HomInfo,			"@hominfo",		1, atcommand_hominfo },
 	{ AtCommand_HomStats,			"@homstats",		1, atcommand_homstats },
+	{ AtCommand_HomShuffle,			"@homshuffle",		60, atcommand_homshuffle },
 	{ AtCommand_ShowMobs,			"@showmobs",		10, atcommand_showmobs },  //KarLaeda
 // add new commands before this line
 	{ AtCommand_Unknown,			NULL,				 1, NULL }
@@ -10005,6 +10007,56 @@ int atcommand_homstats(
 	return 0;
 }
 
+int atcommand_homshuffle(
+	const int fd, struct map_session_data* sd,
+	const char* command, const char* message)
+{
+	struct homun_data *hd;
+	int lv, i;
+	TBL_PC* tsd = sd;
+
+	nullpo_retr(-1, sd);
+
+	if ((!message || !*message) && !sd->hd)
+	{
+		clif_displaymessage(fd, "usage: @homshuffle <Alchemist's name>");
+		clif_displaymessage(fd, "Use this to recalculate your (or someone else's) homunculus growth data");
+		return -1;
+	}
+	if (message && *message) {
+		tsd = map_nick2sd((char*)message);
+		if (!tsd) {
+			clif_displaymessage(fd, msg_txt(3)); // Character not found.
+			return -1;
+		}
+		if (pc_isGM(tsd) > pc_isGM(sd)) {
+			clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player.
+			return -1;
+		}
+	}
+
+	hd = tsd->hd;
+	if(!merc_is_hom_active(hd))
+		return -1;
+	
+	lv = hd->homunculus.level;
+	//Reset values to level 1.
+	merc_reset_stats(hd);
+	//Level it back up
+	for (i = 1; i < lv && hd->exp_next; i++){
+		hd->homunculus.exp += hd->exp_next;
+		merc_hom_levelup(hd);
+	}
+	status_calc_homunculus(hd,0);
+	status_percent_heal(&hd->bl, 100, 100);
+	clif_misceffect2(&hd->bl,568);
+	clif_displaymessage(fd, "Homunculus stats altered");
+	//Print out the new stats
+	//This will send the commands to the invoker since they all use this fd regardless of sd value.
+	atcommand_homstats(fd, tsd, command, message);
+	return 0;
+}
+
 /*==========================================
  * Show Items DB Info   v 1.0
  * originally by [Lupus] eAthena
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 52ca830a5..17b6c363d 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -283,6 +283,7 @@ enum AtCommandType {
 	AtCommand_HomTalk, //[orn]
 	AtCommand_HomInfo, //[Toms]
 	AtCommand_HomStats, //[Skotlex]
+	AtCommand_HomShuffle, //[Skotlex]
 	AtCommand_ShowMobs, //KarLaeda
 	// end <- Ahem, guys, don't place AtCommands after AtCommand_Unknown! [Skotlex]
 	AtCommand_Unknown,
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 3d82e7f99..61df02132 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -730,6 +730,26 @@ void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp)
 	clif_homskillinfoblock(sd);
 }
 
+void merc_reset_stats(struct homun_data *hd)
+{	//Resets a homunc stats back to zero (but doesn't touches hunger or intimacy)
+	struct homunculus_db *db;
+	struct s_homunculus *hom;
+	hom = &hd->homunculus;
+	db = hd->homunculusDB;
+	hom->level = 1;
+	hom->hp = 10;
+	hom->max_hp = db->basemaxHP;
+	hom->max_sp = db->basemaxSP;
+	hom->str = db->baseSTR*10;
+	hom->agi = db->baseAGI*10;
+	hom->vit = db->baseVIT*10;
+	hom->int_= db->baseINT*10;
+	hom->dex = db->baseDEX*10;
+	hom->luk = db->baseLUK*10;
+	hom->exp = 0;
+	hd->exp_next = hexptbl[0];
+}
+
 int read_homunculusdb(void)
 {
 	FILE *fp;
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index e5ba86cfe..91ce62a33 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -62,6 +62,7 @@ void merc_hom_heal(struct homun_data *hd,int hp,int sp);
 int merc_hom_vaporize(struct map_session_data *sd, int flag);
 int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y);
 void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp);
+void merc_reset_stats(struct homun_data *hd);
 void merc_save(struct homun_data *hd);
 int merc_call_homunculus(struct map_session_data *sd);
 int merc_create_homunculus_request(struct map_session_data *sd, int class_);
diff --git a/src/map/skill.c b/src/map/skill.c
index c31ec78cf..6567cfa4a 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -1117,7 +1117,6 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 		break;
 
 	case WZ_STORMGUST:
-		tsc->data[SC_FREEZE].val3++;
 		if(tsc->data[SC_FREEZE].val3 >= 3) //Tharis pointed out that this is normal freeze chance with a base of 300%
 			sc_start(bl,SC_FREEZE,300,skilllv,skill_get_time2(skillid,skilllv));
 		break;
@@ -7121,7 +7120,19 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 						//Otherwise, Knockback attack.
 						skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
 				break;
-
+				case WZ_STORMGUST:
+					if (tsc)
+					{	//This should be safe as skill_additional_effect 
+						//won't be triggered if the attack is absorbed. [Skotlex]
+						//And if the target is already frozen,
+						//the counter is reset when it ends.
+						if (tsc->data[SC_FREEZE].val4 == sg->group_id)
+							tsc->data[SC_FREEZE].val3++; //SG hit counter.
+						else { //New SG
+							tsc->data[SC_FREEZE].val4 = sg->group_id;
+							tsc->data[SC_FREEZE].val3 = 1;
+						}
+					}
 				default:
 					skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);			
 			}
diff --git a/src/map/status.c b/src/map/status.c
index 4194b0c6b..fccf33847 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -5957,13 +5957,7 @@ int status_change_clear(struct block_list *bl,int type)
 
 	sc = status_get_sc(bl);
 
-	if (!sc)
-		return 0;
-
-	if (sc->data[SC_FREEZE].val3)
-		sc->data[SC_FREEZE].val3 = 0; //Reset freeze counter.
-	
-  	if (!sc->count)
+	if (!sc || !sc->count)
 		return 0;
 
 	if(sc->data[SC_DANCING].timer != -1)
-- 
cgit v1.2.3-70-g09d2