浏览代码

-Alpha release for eleanor skill (use with caution)
--Implement : MH_TINDER_BREAKER, MH_CBC, MH_EQC, MH_SONIC_CRAW, MH_SILVERVEIN_RUSH, MH_MIDNIGHT_FRENZY
--Fix style_change not giving sphere when eleanor attacking, and auto set to fighting mode when created.
--Add display msg to know in wich mode we are.
--Remove state check not working well with homon since ??
--Upd MH_SUMMON_LEGION to use summon mob declaration rather then real mob, and set them as agressive by default

-Mob doesn't have fixed casttime anymore bugreport:5697
-Fix few typos
--Enforce logs.sql to check if table not existing. (remove fail at import)
--fix bloodylust effect (temp)
--slave now return final master when killing mob

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17182 54d463be-8e91-2dee-dedb-b68131a5f0ec

glighta 12 年之前
父节点
当前提交
3f28476cd2
共有 14 个文件被更改,包括 307 次插入126 次删除
  1. 7 1
      db/pre-re/mob_db.txt
  2. 4 4
      db/re/skill_cast_db.txt
  3. 4 6
      db/re/skill_require_db.txt
  4. 5 5
      db/re/skill_unit_db.txt
  5. 8 8
      sql-files/logs.sql
  6. 19 10
      src/map/battle.c
  7. 2 0
      src/map/homunculus.c
  8. 7 5
      src/map/mob.c
  9. 3 3
      src/map/pc.c
  10. 164 35
      src/map/skill.c
  11. 0 2
      src/map/skill.h
  12. 47 15
      src/map/status.c
  13. 33 30
      src/map/status.h
  14. 4 2
      tools/config.pl

+ 7 - 1
db/pre-re/mob_db.txt

@@ -1141,4 +1141,10 @@
 2081,E_HYDRA,Suspicious Hydra,Strange Hydra,34,854,1,0,0,7,1,2,100,100,1,1,1,1,1,1,10,12,0,3,41,0x0,1000,800,432,600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 2082,G_PIRANHA,Piranha,Piranha,75,4522,0,0,0,1,182,223,2,10,69,45,30,30,66,35,10,12,1,5,61,0x3295,200,768,768,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
-2308,KO_ZANZOU,Zanzou,Zanzou,1,50,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,7,20,0x0,400,1872,672,480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+// Homunculus S Summons
+2158,S_HORNET,Hornet,Hornet,1,60,1,27,20,1,8,9,2,5,6,1,1,0,6,5,10,12,1,3,21,0x83,400,1872,672,480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+2159,S_GIANT_HORNET,Giant Hornet,Giant Hornet,1,60,1,27,20,1,8,9,2,5,6,1,1,0,6,5,10,12,1,3,21,0x83,400,1872,672,480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+2160,S_LUCIOLA_VESPA,Luciola Vespa,Luciola Vespa,1,60,1,27,20,1,8,9,2,5,6,1,1,0,6,5,10,12,1,3,21,0x83,400,1872,672,480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+2308,KO_ZANZOU,Zanzou,Zanzou,1,50,0,0,0,1,1,1,0,0,1,1,1,1,1,1,1,1,1,7,20,0x0,400,1872,672,480,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+

+ 4 - 4
db/re/skill_cast_db.txt

@@ -1736,7 +1736,7 @@
 //-- MH_SILENT_BREEZE
 8026,2000,0,0,9000:12000:15000:18000:21000,0,0,1000:800:600:400:200
 //-- MH_STYLE_CHANGE
-//8027,0,0,0,0,0,0,0
+8027,0,0,0,0,0,0,0
 //-- MH_SONIC_CRAW
 //8028,0,0,0,0,0,0,0
 //-- MH_SILVERVEIN_RUSH
@@ -1754,11 +1754,11 @@
 //-- MH_ANGRIFFS_MODUS
 8035,200:400:600:800:1000,0,0,30000:45000:60000:75000:90000,0,0,-1
 //-- MH_TINDER_BREAKER
-//8036,0,0,0,5000,0,0,0
+8036,0,0,0,5000,0,0,0
 //-- MH_CBC
-//8037,0,0,0,0,0,0,0
+8037,0,0,0,0,0,0,0
 //-- MH_EQC
-//8038,0,0,0,0,0,0,0
+8038,0,0,0,0,0,0,0
 //-- MH_MAGMA_FLOW
 8039,2000:2500:3000:3500:4000,0,0,30000:45000:60000:75000:90000,0,0,2000:1500:1000:500:-1
 //-- MH_GRANITIC_ARMOR

+ 4 - 6
db/re/skill_require_db.txt

@@ -26,8 +26,6 @@
 //  poisonweapon = Requires to be under Poisoning Weapon.
 //  rollingcutter = Requires at least one Rotation Counter from Rolling Cutter.
 //  elementalspirit = Requires to have an Elemental Spirit summoned.
-//  mh_fighting = Requires Eleanor fighthing mode
-//  mh_grappling = Requires Eleanor grappling mode
 //  peco = Requires riding a peco
 
 5,0,0,8:8:8:8:8:15:15:15:15:15,0,0,0,0:1:2:3:4:5:6:7:8:9:10:12:13:14:15:16:17:18:19:20:21:22,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SM_BASH#バッシュ#
@@ -175,7 +173,7 @@
 230,0,0,15,0,0,0,99,0,0,none,0,7136,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_ACIDTERROR#アシッドテラ?#
 231,0,0,1,0,0,0,99,0,0,none,0,501,1,502,1,503,1,504,1,505,1,522,1,526,1,608,1,607,1,657,1	//AM_POTIONPITCHER#ポ?ションピッチャ?#
 232,0,0,20,0,0,0,99,0,0,none,0,7137,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CANNIBALIZE#バイオプラント#
-233,0,0,10,0,0,0,99,0,0,none,0,7138,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_SPHEREMINE#スフィア?マン#
+233,0,0,10,0,0,0,99,0,0,none,0,7138,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_SPHEREMINE#スフィア?マ?Cン#
 234,0,0,30,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CP_WEAPON#ケミカルウェポンチャ?ジ#
 235,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CP_SHIELD#ケミカルシ?ルドチャ?ジ#
 236,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//AM_CP_ARMOR#ケミカルア?マ?チャ?ジ#
@@ -858,7 +856,7 @@
 8025,0,0,90:100:110:120:130,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_XENO_SLASHER#Xeno Slasher#
 8026,0,0,45:54:63:72:81,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_SILENT_BREEZE#Silent Breeze#
 8027,0,0,35,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_STYLE_CHANGE#Style Change#
-8028,0,0,20:25:30:35:40,0,0,0,99,0,0,mh_fighting,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_SONIC_CRAW#Sonic Claw#
+8028,0,0,20:25:30:35:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_SONIC_CRAW#Sonic Claw#
 8029,0,0,10:15:20:25:30,0,0,0,99,0,0,none,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_SILVERVEIN_RUSH#Silver Bain Rush#
 8030,0,0,8:16:24:32:40,0,0,0,99,0,0,none,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_MIDNIGHT_FRENZY#Midnight Frenzy#
 8031,0,0,40:45:50:55:60,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_STAHL_HORN#Steel Horn#
@@ -866,8 +864,8 @@
 8033,0,0,80:90:100:110:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_STEINWAND#Stone Wall#
 8034,0,0,60:68:76:84:100,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_HEILIGE_STANGE#Holy Pole#
 8035,0,0,60:65:70:75:80,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_ANGRIFFS_MODUS#Attack Mode#
-8036,0,0,20:25:30:35:40,0,0,0,99,0,0,mh_grappling,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_TINDER_BREAKER#Tinder Breaker#
-8037,0,0,10:20:30:40:50,0,0,0,99,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_CBC#Continual Break Combo#
+8036,0,0,20:25:30:35:40,0,0,0,99,0,0,none,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_TINDER_BREAKER#Tinder Breaker#
+8037,0,0,10:20:30:40:50,0,0,0,99,0,0,none,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_CBC#Continual Break Combo#
 8038,0,0,24:28:32:36:40,0,0,0,99,0,0,none,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_EQC#Eternal Quick Combo#
 8039,0,0,34:38:42:46:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_MAGMA_FLOW#Magma Flow#
 8040,0,0,54:58:62:66:70,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//MH_GRANITIC_ARMOR#Granitic Armor#

+ 5 - 5
db/re/skill_unit_db.txt

@@ -161,7 +161,7 @@
 3010,0xfc,    ,  0, 1,1000,enemy, 0x020	//KO_MAKIBISHI
 
 8020,0xf5,    ,  0, 3,2300:2100:1900:1700:1500,enemy,   0x018	//MH_POISON_MIST
-8033,0x7e,    ,  0, 0,  -1,all,   0x003	//MH_STEINWAND 
+8033,0x7e,    ,  0, 0,  -1,all,   0x003	//MH_STEINWAND
 8025,0x86,    ,  0, 2:2:3:3:4,1000,enemy, 0x018	//MH_XENO_SLASHER
 8041,0xf6,    ,  1:1:2:2:3, 0,2000,enemy,   0x01A	//MH_LAVA_SLIDE
 8043,0xf7,    ,  1, 0,-1,enemy,   0x2018	//MH_VOLCANIC_ASH
@@ -177,7 +177,7 @@
 8409,0xef,    ,  0, 1,1000,friend,0x018	//EL_ZEPHYR
 8412,0xf0,    ,  0, 1,  -1,friend,0x018	//EL_POWER_OF_GAIA
 
-10006,0xc1,   ,  2, 0,  -1,guild, 0x040	//GD_LEADERSHIP 
-10007,0xc2,   ,  2, 0,  -1,guild, 0x040	//GD_GLORYWOUNDS 
-10008,0xc3,   ,  2, 0,  -1,guild, 0x040	//GD_SOULCOLD 
-10009,0xc4,   ,  2, 0,  -1,guild, 0x040	//GD_HAWKEYES 
+10006,0xc1,   ,  2, 0,  -1,guild, 0x040	//GD_LEADERSHIP
+10007,0xc2,   ,  2, 0,  -1,guild, 0x040	//GD_GLORYWOUNDS
+10008,0xc3,   ,  2, 0,  -1,guild, 0x040	//GD_SOULCOLD
+10009,0xc4,   ,  2, 0,  -1,guild, 0x040	//GD_HAWKEYES

+ 8 - 8
sql-files/logs.sql

@@ -6,7 +6,7 @@
 
 #Database: ragnarok
 #Table: picklog
-CREATE TABLE `picklog` (
+CREATE TABLE IF NOT EXISTS `picklog` (
   `id` int(11) NOT NULL auto_increment,
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `char_id` int(11) NOT NULL default '0',
@@ -27,7 +27,7 @@ CREATE TABLE `picklog` (
 #ZenyLog types (M)onsters,(T)rade,(V)ending Sell/Buy,(S)hop Sell/Buy,(N)PC Change amount,(A)dministrators,(E)Mail,(B)uying Store
 #Database: ragnarok
 #Table: zenylog
-CREATE TABLE `zenylog` (
+CREATE TABLE IF NOT EXISTS `zenylog` (
   `id` int(11) NOT NULL auto_increment,
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `char_id` int(11) NOT NULL default '0',
@@ -41,7 +41,7 @@ CREATE TABLE `zenylog` (
 
 #Database: ragnarok
 #Table: branchlog
-CREATE TABLE `branchlog` (
+CREATE TABLE IF NOT EXISTS `branchlog` (
   `branch_id` mediumint(9) unsigned NOT NULL auto_increment,
   `branch_date` datetime NOT NULL default '0000-00-00 00:00:00',
   `account_id` int(11) NOT NULL default '0',
@@ -55,7 +55,7 @@ CREATE TABLE `branchlog` (
 
 #Database: ragnarok
 #Table: mvplog
-CREATE TABLE `mvplog` (
+CREATE TABLE IF NOT EXISTS `mvplog` (
   `mvp_id` mediumint(9) unsigned NOT NULL auto_increment,
   `mvp_date` datetime NOT NULL default '0000-00-00 00:00:00',
   `kill_char_id` int(11) NOT NULL default '0',
@@ -68,7 +68,7 @@ CREATE TABLE `mvplog` (
 
 #Database: ragnarok
 #Table: atcommandlog
-CREATE TABLE `atcommandlog` (
+CREATE TABLE IF NOT EXISTS `atcommandlog` (
   `atcommand_id` mediumint(9) unsigned NOT NULL auto_increment,
   `atcommand_date` datetime NOT NULL default '0000-00-00 00:00:00',
   `account_id` int(11) unsigned NOT NULL default '0',
@@ -83,7 +83,7 @@ CREATE TABLE `atcommandlog` (
 
 #Database: ragnarok
 #Table: npclog
-CREATE TABLE `npclog` (
+CREATE TABLE IF NOT EXISTS `npclog` (
   `npc_id` mediumint(9) unsigned NOT NULL auto_increment,
   `npc_date` datetime NOT NULL default '0000-00-00 00:00:00',
   `account_id` int(11) unsigned NOT NULL default '0',
@@ -99,7 +99,7 @@ CREATE TABLE `npclog` (
 #ChatLog types Gl(O)bal,(W)hisper,(P)arty,(G)uild,(M)ain chat
 #Database: ragnarok
 #Table: chatlog
-CREATE TABLE `chatlog` (
+CREATE TABLE IF NOT EXISTS `chatlog` (
   `id` bigint(20) NOT NULL auto_increment,
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `type` enum('O','W','P','G','M') NOT NULL default 'O',
@@ -118,7 +118,7 @@ CREATE TABLE `chatlog` (
 
 #Database: ragnarok
 #Table: loginlog
-CREATE TABLE `loginlog` (
+CREATE TABLE IF NOT EXISTS `loginlog` (
   `time` datetime NOT NULL default '0000-00-00 00:00:00',
   `ip` varchar(15) NOT NULL default '',
   `user` varchar(23) NOT NULL default '',

+ 19 - 10
src/map/battle.c

@@ -1201,7 +1201,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 		if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
 			status_change_spread(src, bl);
                 if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
-                    TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+                    TBL_HOM *hd = BL_CAST(BL_HOM,src);
                     if (hd) hom_addspiritball(hd, 10);
                 }
 	}
@@ -2113,12 +2113,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 						sd->inventory_data[index] &&
 						sd->inventory_data[index]->type == IT_WEAPON)
 						wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight
-					
+
 					ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
 				} else {
 					wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); //Monsters have no weight and use ATK instead
 				}
-				
+
 				i = sstatus->str/10;
 				i*=i;
 				ATK_ADD(i); //Add str bonus.
@@ -2973,7 +2973,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 					skillratio += 400 + 100 * skill_lv;
 					break;
 				case MH_LAVA_SLIDE:
-					skillratio = 70 * skill_lv;
+					skillratio += -100 + 70 * skill_lv;
+					break;
+				case MH_SONIC_CRAW:
+					skillratio += -100 + 40 * skill_lv;
+					break;
+				case MH_SILVERVEIN_RUSH:
+					skillratio += -100 + 150 * skill_lv;
+					break;
+				case MH_MIDNIGHT_FRENZY:
+					skillratio += -100 + 300 * skill_lv;
 					break;
 				case MH_TINDER_BREAKER:
 				case MH_MAGMA_FLOW:
@@ -4090,14 +4099,14 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						skillratio += 100 * skill_lv;
 						break;
 					case MH_XENO_SLASHER:
-					    if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700
-					    else skillratio += 400 + 100 * skill_lv; //700:900
-					    break;
+						if(skill_lv%2) skillratio += 350 + 50 * skill_lv; //500:600:700
+						else skillratio += 400 + 100 * skill_lv; //700:900
+						break;
 					case MH_HEILIGE_STANGE:
-					    skillratio += 400 + 250 * skill_lv;
-					    break;
+						skillratio += 400 + 250 * skill_lv;
+						break;
 					case MH_POISON_MIST:
-					    skillratio += 100 * skill_lv;
+						skillratio += 100 * skill_lv;
 						break;
 				}
 

+ 2 - 0
src/map/homunculus.c

@@ -782,6 +782,8 @@ int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom)
 
 	map_addiddb(&hd->bl);
 	status_calc_homunculus(hd,1);
+	if(hom->class_ == 6052) //eleanor
+	    sc_start(&hd->bl, SC_STYLE_CHANGE, 100, MH_MD_FIGHTING, -1);
 
 	hd->hungry_timer = INVALID_TIMER;
 	return 0;

+ 7 - 5
src/map/mob.c

@@ -2554,11 +2554,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 	if( !rebirth ) { // Only trigger event on final kill
 		md->status.hp = 0; //So that npc_event invoked functions KNOW that mob is dead
 		if( src ) {
-			switch( src->type ) {
-				case BL_PET: sd = ((TBL_PET*)src)->msd; break;
-				case BL_HOM: sd = ((TBL_HOM*)src)->master; break;
-				case BL_MER: sd = ((TBL_MER*)src)->master; break;
-				case BL_ELEM: sd = ((TBL_ELEM*)src)->master; break;
+			switch( src->type ) { //allowed type
+				case BL_PET:
+				case BL_HOM:
+				case BL_MER:
+				case BL_ELEM:
+				case BL_MOB:
+				    sd = BL_CAST(BL_PC,battle_get_master(src));
 			}
 		}
 

+ 3 - 3
src/map/pc.c

@@ -3853,7 +3853,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
 			}
 		}
 	}
-	
+
 	if( i >= MAX_INVENTORY )
 	{
 		i = pc_search_inventory(sd,0);
@@ -6924,7 +6924,7 @@ int pc_readparam(struct map_session_data* sd,int type)
 		case SP_DEFELE:		     val = sd->battle_status.def_ele; break;
 #ifndef RENEWAL_CAST
 		case SP_VARCASTRATE:
-#endif	
+#endif
 		case SP_CASTRATE:
 				val = sd->castrate+=val;
 			break;
@@ -7390,7 +7390,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
 		/* going off star glad lineage, reset feel to not store no-longer-used vars in the database */
 		pc_resetfeel(sd);
 	}
-	
+
 	sd->status.class_ = job;
 	fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
 	sd->class_ = (unsigned short)b_class;

+ 164 - 35
src/map/skill.c

@@ -661,6 +661,77 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
 	    case MH_ANGRIFFS_MODUS:
 		if(hd->sc.data[SC_GOLDENE_FERSE])
 		    return 1;
+	    case MH_TINDER_BREAKER:
+	    case MH_CBC:
+	    case MH_EQC:
+	    case MH_SONIC_CRAW:
+	    case MH_SILVERVEIN_RUSH:
+	    case MH_MIDNIGHT_FRENZY: {
+		    struct status_change_entry *sce = hd->sc.data[SC_STYLE_CHANGE];
+		    TBL_PC *sd;
+		    if(!(sd=hd->master)) return 1; //we need a master
+		    if(!sce || !sce->val3){ //homon doesn't have status or it's not a combo
+			if(skill_id != MH_SONIC_CRAW && skill_id != MH_TINDER_BREAKER)
+			    return 1;
+		    }
+
+		    switch(skill_id){
+			case MH_SONIC_CRAW:
+			case MH_SILVERVEIN_RUSH:
+			case MH_TINDER_BREAKER:
+			case MH_CBC:
+			    if(!hd->homunculus.spiritball) {
+				clif_colormes(sd,COLOR_RED,"Homon need some spiritballs");
+				return 1;
+			    }
+			    break;
+
+			case MH_MIDNIGHT_FRENZY:
+			case MH_EQC:
+			    if(hd->homunculus.spiritball < 2) {
+				clif_colormes(sd,COLOR_RED,"Homon need at least 2 spiritballs");
+				return 1;
+			    }
+			    break;
+		    }
+
+		    switch(skill_id){
+			case MH_SONIC_CRAW:
+			case MH_SILVERVEIN_RUSH:
+			case MH_MIDNIGHT_FRENZY:
+			    if (!(sce->val1 == MH_MD_FIGHTING)){
+				    clif_colormes(sd,COLOR_RED,"Homon need to be in fighting mode to use that skill");
+				    return 1;
+			    }
+			    break;
+
+			case MH_TINDER_BREAKER:
+			case MH_CBC:
+			case MH_EQC:
+			    if (!(sce->val1 == MH_MD_GRAPPLING)){
+				    clif_colormes(sd,COLOR_RED,"Homon need to be in grappling mode to use that skill");
+				    return 1;
+			    }
+			    break;
+		    }
+
+		    //now let really be specific
+		    switch(skill_id){
+			case MH_TINDER_BREAKER:
+			    if(sce->val3 == MH_EQC && (gettick() - sce->val4 <= 2000)) break;
+			    else break; //im not a combo what should I do ??
+			case MH_CBC: if(sce->val3 == MH_TINDER_BREAKER && (gettick() - sce->val4 <= 2000)) break;
+			case MH_EQC: if(sce->val3 == MH_CBC && (gettick() - sce->val4 <= 2000)) break;
+
+			case MH_SONIC_CRAW:
+			    if(sce->val3 == MH_MIDNIGHT_FRENZY && (gettick() - sce->val4 <= 2000)) break;
+			    else break; //im not a combo what should I do ??
+			case MH_SILVERVEIN_RUSH: if(sce->val3 == MH_SONIC_CRAW && (gettick() - sce->val4 <= 2000)) break;
+			case MH_MIDNIGHT_FRENZY: if(sce->val3 == MH_SILVERVEIN_RUSH && (gettick() - sce->val4 <= 2000)) break;
+			default:
+			    return 1;
+		    }
+		}
 		break;
 	}
 
@@ -1406,6 +1477,12 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
 	case MH_NEEDLE_OF_PARALYZE:
 		sc_start(bl, SC_PARALYSIS, 40 + (5*skill_lv), skill_lv, skill_get_time(skill_id, skill_lv));
 		break;
+	case MH_SILVERVEIN_RUSH:
+		sc_start4(bl,SC_STUN,20 + (5*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv));
+		break;
+	case MH_MIDNIGHT_FRENZY:
+		sc_start4(bl,SC_FEAR,20 + (4*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv));
+		break;
 	}
 
 	if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
@@ -4627,19 +4704,67 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 	case MH_NEEDLE_OF_PARALYZE:
 		skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
 		break;
-        case MH_TINDER_BREAKER:
-                if (unit_movepos(src, bl->x, bl->y, 1, 1)) {
+	case MH_SONIC_CRAW:
+	case MH_TINDER_BREAKER:
+	case MH_MIDNIGHT_FRENZY:
+	case MH_SILVERVEIN_RUSH:
+	case MH_CBC:
+	case MH_EQC: {
+		TBL_HOM *hd = BL_CAST(BL_HOM,src);
+		int8 k=0;
+		int duration;
+		struct status_change_entry *sce;
+		struct block_list *tbl = NULL; //target
+
+		if(!hd){
+		    clif_colormes(sd,COLOR_RED,"Only homon are support this skill atm, can't used it by other");
+		    map_freeblock_unlock();
+		    return 1;
+		}
+		if(hd->sc.count && (sce=hd->sc.data[SC_STYLE_CHANGE])){
+		    //val1 = mode
+		    if(!sce->val2) sce->val2 = bl->id; //memo target (only sonic slaw and tinder should)
+		    tbl = map_id2bl(sce->val2);
+		    sce->val3 = skill_id;
+		    sce->val4 = gettick();
+		}
+		switch(skill_id){
+		    case MH_SONIC_CRAW: {
+			    int nb_sphere = hd->homunculus.spiritball;
+			    for(k=0; k<=nb_sphere; k++){ //attack for each sphere active
+				skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+			    }
+	//		    hom_delspiritball(hd, nb_sphere, 0); //remove them all if we remove can't coninue combo
+			    break;
+		    }
+		    case MH_SILVERVEIN_RUSH:
+		    case MH_MIDNIGHT_FRENZY:
+			    hom_delspiritball(hd,skill_id==MH_SILVERVEIN_RUSH?1:2,0);
+			    skill_attack(skill_get_type(skill_id),src,src,tbl,skill_id,skill_lv,tick,flag);
+			    break;
+		    case MH_TINDER_BREAKER:
+			if (unit_movepos(src, bl->x, bl->y, 1, 1)) {
 #if PACKETVER >= 20111005
-			clif_snap(src, bl->x, bl->y);
+				clif_snap(src, bl->x, bl->y);
 #else
-			clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick);
+				clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick);
 #endif
+			}
+
+		    case MH_CBC:
+		    case MH_EQC:
+			    duration = (status_get_str(src)*2 - status_get_str(bl))/10;//custom need real formula
+			    hom_delspiritball(hd,skill_id==MH_EQC?2:1,0); //only EQC consume 2 in grp 2
+			    if(skill_id==MH_TINDER_BREAKER)
+				sc_start2(src,status_skill2sc(skill_id),100,skill_lv,bl->id,duration);
+			    else
+				sc_start(bl,status_skill2sc(skill_id),100,skill_lv,duration);
+			    skill_attack(skill_get_type(skill_id),src,src,tbl,skill_id,skill_lv,tick,flag);
+			    //TODO add bonus for dmg SP ? on battle
+			    break;
 		}
-                clif_skill_nodamage(src,bl,skill_id,skill_lv,
-			sc_start4(bl,SC_CLOSECONFINE2,100,skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv)));
-                skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
 		break;
-
+	}
 	case 0:/* no skill - basic/normal attack */
 		if(sd) {
 			if (flag & 3){
@@ -9044,29 +9169,44 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		    if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info
 		}
 		//don't break need to start status and start block timer
-	case MH_STYLE_CHANGE:
+	case MH_STYLE_CHANGE: {
+	    struct status_change_entry *sce;
+	    if(hd && (sce=hd->sc.data[SC_STYLE_CHANGE])){ //in preparation for other bl usage
+		if(sce->val1 == MH_MD_FIGHTING) sce->val1 = MH_MD_GRAPPLING;
+		else sce->val1 = MH_MD_FIGHTING;
+		if(hd->master && hd->sc.data[SC_STYLE_CHANGE]) {
+		    int mode = hd->sc.data[SC_STYLE_CHANGE]->val1;
+		    char output[128];
+		    safesnprintf(output,sizeof(output),"Eleanor is now in %s mode",(sce->val1==MH_MD_FIGHTING?"fighthing":"grappling"));
+		    clif_colormes(hd->master,COLOR_RED,output);
+		}
+	    }
+	    break;
+	}
         case MH_MAGMA_FLOW:
         case MH_PAIN_KILLER:
            sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv));
            if (hd)
                 skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
            break;
+
         case MH_SUMMON_LEGION:
             {
-                int summons[5] = {1004, 1303, 1303, 1994, 1994};
+                int summons[5] = {2158, 2159, 2159, 2160, 2160};
                 int qty[5] =     {3   , 3   , 4   , 4   , 5};
-                struct mob_data *md;
+                struct mob_data *sum_md;
                 int i;
 
                 for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
-                    md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
-                    if (md) {
-                        md->master_id =  src->id;
-                        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);
-                        mob_spawn(md); //Now it is ready for spawning.
-                        sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000);
+                    sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
+                    if (sum_md) {
+                        sum_md->master_id =  src->id;
+			sum_md->special_state.ai = 1;
+                        if (sum_md->deletetimer != INVALID_TIMER)
+                            delete_timer(sum_md->deletetimer, mob_timer_delete);
+                        sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0);
+                        mob_spawn(sum_md); //Now it is ready for spawning.
+                        sc_start4(&sum_md->bl, SC_MODECHANGE, 100, 1, 0, MD_CANATTACK|MD_AGGRESSIVE, 0, 60000);
                     }
                 }
 		if (hd)
@@ -10951,7 +11091,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
 
 		if( !group->state.song_dance && !map_getcell(src->m,ux,uy,CELL_CHKREACH) )
 			continue; // don't place skill units on walls (except for songs/dances/encores)
-		if( battle_config.skill_wall_check && skill_get_unit_flag(skill_id)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
+		if( battle_config.skill_wall_check && unit_flag&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
 			continue; // no path between cell and center of casting.
 
 		switch( skill_id )
@@ -11014,7 +11154,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
 				val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance
 			break;
 		}
-		if (skill_get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
+		if (unit_flag&UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
 			val2 |= UF_RANGEDSINGLEUNIT; // center.
 
 		if( range <= 0 )
@@ -13221,16 +13361,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
 			return 0;
 		}
 		break;
-	case ST_MH_FIGHTING:
-		if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_FIGHTING)){
-			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
-			return 0;
-		}
-	case ST_MH_GRAPPLING:
-		if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_GRAPPLING)){
-			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
-			return 0;
-		}
 	case ST_PECO:
 		if(!pc_isriding(sd)) {
 			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -13372,7 +13502,6 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
 			}
 			break;
 	}
-
 	status = &sd->battle_status;
 
 	require = skill_get_requirement(sd,skill_id,skill_lv);
@@ -13863,7 +13992,9 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16
 	if( time < 0 )
 		return 0;
 
-	if( fixed == 0 ){
+	if(bl->type == BL_MOB)
+	    fixed = 0; //mob as no fixed time
+	else if( fixed == 0 ){
 		fixed = (int)time * 20 / 100; // fixed time
 		time = time * 80 / 100; // variable time
 	}else if( fixed < 0 ) // no fixed cast time
@@ -17684,8 +17815,6 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current)
 	else if( strcmpi(split[10],"elementalspirit")     == 0 ) skill_db[idx].state = ST_ELEMENTALSPIRIT;
 	else if( strcmpi(split[10],"poisonweapon")        == 0 ) skill_db[idx].state = ST_POISONINGWEAPON;
 	else if( strcmpi(split[10],"rollingcutter")       == 0 ) skill_db[idx].state = ST_ROLLINGCUTTER;
-	else if( strcmpi(split[10],"mh_fighting")         == 0 ) skill_db[idx].state = ST_MH_FIGHTING;
-	else if( strcmpi(split[10],"mh_grappling")        == 0 ) skill_db[idx].state = ST_MH_GRAPPLING;
 	else if( strcmpi(split[10],"peco")                == 0 ) skill_db[idx].state = ST_PECO;
 	/**
 	 * Unknown or no state

+ 0 - 2
src/map/skill.h

@@ -402,8 +402,6 @@ enum {
 	ST_ELEMENTALSPIRIT,
 	ST_POISONINGWEAPON,
 	ST_ROLLINGCUTTER,
-	ST_MH_FIGHTING,
-	ST_MH_GRAPPLING,
 	ST_PECO,
 };
 

+ 47 - 15
src/map/status.c

@@ -509,9 +509,9 @@ void initChangeTables(void) {
 	set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
 
 	add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE);
-        set_sc( MH_TINDER_BREAKER      , SC_CLOSECONFINE2   , SI_CLOSECONFINE2   , SCB_NONE );
-	set_sc( MH_TINDER_BREAKER      , SC_CLOSECONFINE    , SI_CLOSECONFINE    , SCB_FLEE );
-
+	set_sc(MH_TINDER_BREAKER, SC_TINDER_BREAKER, SI_TINDER_BREAKER, SCB_FLEE);
+	set_sc(MH_CBC, SC_CBC, SI_CBC, SCB_FLEE);
+	set_sc(MH_EQC, SC_EQC, SI_EQC, SCB_DEF2|SCB_BATK);
 
 	add_sc( MER_CRASH            , SC_STUN            );
 	set_sc( MER_PROVOKE          , SC_PROVOKE         , SI_PROVOKE         , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
@@ -647,7 +647,7 @@ void initChangeTables(void) {
 	set_sc( SC_STRIPACCESSARY    , SC__STRIPACCESSORY , SI_STRIPACCESSARY  , SCB_DEX|SCB_INT|SCB_LUK );
 	set_sc_with_vfx( SC_MANHOLE           , SC__MANHOLE        , SI_MANHOLE         , SCB_NONE );
 	add_sc( SC_CHAOSPANIC        , SC_CONFUSION );
-	set_sc_with_vfx( SC_BLOODYLUST        , SC__BLOODYLUST     , SI_BLOODYLUST      , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN );
+	set_sc_with_vfx( SC_BLOODYLUST        , SC__BLOODYLUST     , SI_BERSERK      , SCB_DEF | SCB_DEF2 | SCB_MDEF | SCB_MDEF2 | SCB_FLEE | SCB_SPEED | SCB_ASPD | SCB_MAXHP | SCB_REGEN );
 	/**
 	 * Sura
 	 **/
@@ -4563,6 +4563,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
 		batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100;
 	if( sc->data[SC_ZANGETSU] )
 		batk += batk * sc->data[SC_ZANGETSU]->val2 / 100;
+	if(sc->data[SC_EQC])
+		batk -= batk * sc->data[SC_EQC]->val3 / 100;
 
 	return (unsigned short)cap_value(batk,0,USHRT_MAX);
 }
@@ -5014,6 +5016,8 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
 	}
 	if (sc->data[SC_PARALYSIS])
 		def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100;
+	if(sc->data[SC_EQC])
+		def2 -= def2 * sc->data[SC_EQC]->val2 / 100;
 
 #ifdef RENEWAL
 	return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
@@ -5835,7 +5839,7 @@ struct status_data *status_get_base_status(struct block_list *bl)
 		case BL_HOM: return &((TBL_HOM*)bl)->base_status;
 		case BL_MER: return &((TBL_MER*)bl)->base_status;
 		case BL_ELEM: return &((TBL_ELEM*)bl)->base_status;
-		case BL_NPC:  return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL); 
+		case BL_NPC:  return ((mobdb_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);
 		default:
 			return NULL;
 	}
@@ -5853,8 +5857,8 @@ defType status_get_def(struct block_list *bl) {
 
 unsigned short status_get_speed(struct block_list *bl)
 {
-	if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex] 
-		return ((struct npc_data *)bl)->speed; 
+	if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex]
+		return ((struct npc_data *)bl)->speed;
 	return status_get_status_data(bl)->speed;
 }
 
@@ -6338,8 +6342,8 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
 		tick -= 30*status->int_;
 		break;
         case SC_PARALYSIS:
-            tick -= 50 * (status->vit + status->luk); //(1000/20);
-            break;
+		tick -= 50 * (status->vit + status->luk); //(1000/20);
+		break;
 	default:
 		//Effect that cannot be reduced? Likely a buff.
 		if (!(rnd()%10000 < rate))
@@ -6838,7 +6842,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			case SC_ROKISWEIL:
 			case SC_FOGWALL:
 			case SC_FREEZING:
-			case SC_BURNING: 
+			case SC_BURNING:
 			case SC_MARSHOFABYSS:
 			case SC_ADORAMUS:
 			case SC_PARALYSIS:
@@ -8643,9 +8647,24 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			    break;
                         case SC_STYLE_CHANGE: //[Lighta] need real info
                             tick = -1;
-                            if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING;
-                            else val2 = MH_MD_FIGHTING;
                             break;
+			case SC_CBC:
+			    val2 = 10; //hp % dmg [not sure]
+			    val3 = 10; //sp % dmg [not sure]
+			    tick = max(tick,5000); //min 5s (test)
+			    val4 = tick/1000; //dmg each sec
+			    tick = 1000;
+			    break;
+			case SC_EQC:
+			    val2 = 25; //def % reduc [not sure]
+			    val3 = 25; //atk % reduc [not sure]
+			    tick = max(tick,5000); //min 5s (test)
+			    break;
+			case SC_TINDER_BREAKER:
+			    //val1 = skilllv
+			    //val2 = src->id
+			    tick = max(tick,5000); //min 5s (test)
+			    break;
 		default:
 			if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
 			{	//Status change with no calc, no icon, and no skill associated...?
@@ -8957,9 +8976,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		case SC_MERC_SPUP:
 			status_percent_heal(bl, 0, 100); // Recover Full SP
 			break;
-		/**
-		 * Ranger
-		 **/
 		case SC_WUGDASH:
 			{
 				struct unit_data *ud = unit_bl2ud(bl);
@@ -9006,6 +9022,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		case SC_RAISINGDRAGON:
 			sce->val2 = status->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
 			break;
+		case SC_TINDER_BREAKER:
+			sc_start2(map_id2bl(val2),SC_CLOSECONFINE2,100,val1,bl->id,tick);
+			break;
+		case SC_EQC:
+			status_change_end(bl,SC_TINDER_BREAKER,INVALID_TIMER);
+			break;
 	}
 
 	if( opt_flag&2 && sd && sd->touching_id )
@@ -9377,6 +9399,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 					skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL );
 			}
 			break;
+		case SC_TINDER_BREAKER:
 		case SC_CLOSECONFINE2:
 			{
 				struct block_list *src = sce->val2?map_id2bl(sce->val2):NULL;
@@ -10660,6 +10683,15 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			return 0;
 		}
 		break;
+	case SC_CBC:
+	    if(--(sce->val4) >= 0) { //drain hp/sp
+		int hp = (status->max_hp * sce->val2) / 100;
+		int sp = (status->max_sp * sce->val3) / 100;
+		if( !status_charge(bl,hp,sp) ) break;
+		sc_timer_next(1000+tick,status_change_timer,bl->id, data);
+		return 0;
+	    }
+	    break;
 	}
 
 	// default for all non-handled control paths is to end the status

+ 33 - 30
src/map/status.h

@@ -33,7 +33,7 @@ enum refine_type {
 
 int status_get_refine_chance(enum refine_type wlv, int refine);
 
-// Status changes listing. These code are for use by the server. 
+// Status changes listing. These code are for use by the server.
 typedef enum sc_type {
 	SC_NONE = -1,
 
@@ -51,7 +51,7 @@ typedef enum sc_type {
 	SC_BLEEDING,
 	SC_DPOISON, //10
 	SC_COMMON_MAX = 10, // end
-	
+
 	//Next up, we continue on 20, to leave enough room for additional "common" ailments in the future.
 	SC_PROVOKE = 20,
 	SC_ENDURE,
@@ -292,7 +292,7 @@ typedef enum sc_type {
 	SC_SUMMER,
 	SC_EXPBOOST,
 	SC_ITEMBOOST,
-	SC_BOSSMAPINFO, 
+	SC_BOSSMAPINFO,
 	SC_LIFEINSURANCE, //260
 	SC_INCCRI,
 	//SC_INCDEF,
@@ -631,23 +631,26 @@ typedef enum sc_type {
 	SC_ZANGETSU,
 	SC_GENSOU,
 	SC_AKAITSUKI,
-	
+
 	//homon S
-	SC_STYLE_CHANGE,        
-    SC_GOLDENE_FERSE,
-    SC_ANGRIFFS_MODUS,
-    SC_ERASER_CUTTER,
-    SC_OVERED_BOOST,        
-    SC_LIGHT_OF_REGENE,
-    SC_ASH,
-    SC_GRANITIC_ARMOR,
-    SC_MAGMA_FLOW,
-    SC_PYROCLASTIC,
-    SC_PARALYSIS,
-    SC_PAIN_KILLER,
+	SC_STYLE_CHANGE,
+	SC_TINDER_BREAKER,
+	SC_CBC,
+	SC_EQC,
+	SC_GOLDENE_FERSE,
+	SC_ANGRIFFS_MODUS,
+	SC_ERASER_CUTTER,
+	SC_OVERED_BOOST,
+	SC_LIGHT_OF_REGENE,
+	SC_ASH,
+	SC_GRANITIC_ARMOR,
+	SC_MAGMA_FLOW,
+	SC_PYROCLASTIC,
+	SC_PARALYSIS,
+	SC_PAIN_KILLER,
+
 
-	
-#ifdef RENEWAL	
+#ifdef RENEWAL
 	SC_EXTREMITYFIST2,
 #endif
 
@@ -1038,10 +1041,10 @@ enum si_type {
 	SI_NEUTRALBARRIER_MASTER = 378,
 	SI_STEALTHFIELD = 379,
 	SI_STEALTHFIELD_MASTER = 380,
-	SI_MANU_ATK = 381, 
-	SI_MANU_DEF = 382, 
-	SI_SPL_ATK = 383, 
-	SI_SPL_DEF = 384, 
+	SI_MANU_ATK = 381,
+	SI_MANU_DEF = 382,
+	SI_SPL_ATK = 383,
+	SI_SPL_DEF = 384,
 	SI_REPRODUCE = 385,
 	SI_MANU_MATK = 386,
 	SI_SPL_MATK = 387,
@@ -1474,18 +1477,18 @@ enum {
 	OPTION_DRAGON4   = 0x02000000,
 	OPTION_DRAGON5   = 0x04000000,
 	OPTION_MOUNTING  = 0x08000000,
-	
+
 #ifndef NEW_CARTS
 	OPTION_CART1     = 0x00000008,
 	OPTION_CART2     = 0x00000080,
 	OPTION_CART3     = 0x00000100,
 	OPTION_CART4     = 0x00000200,
 	OPTION_CART5     = 0x00000400,
-	
+
 	/*  compound constant for older carts */
 	OPTION_CART      = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5,
 #endif
-	
+
 	// compound constants
 	OPTION_DRAGON    = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5,
 	OPTION_MASK      = ~OPTION_INVISIBLE,
@@ -1509,7 +1512,7 @@ enum scs_flag {
 	SCS_NOPICKITEM      = 0x00000008, /* player unable to pick up items */
 	SCS_NODROPITEMCOND  = 0x00000010, /* cond flag for nodropitem */
 	SCS_NODROPITEM      = 0x00000020, /* player unable to drop items */
-	SCS_NOCASTCOND      = 0x00000040, /* cond flag for nocast */	
+	SCS_NOCASTCOND      = 0x00000040, /* cond flag for nocast */
 	SCS_NOCAST          = 0x00000080, /* unit unable to cast skills */
 };
 
@@ -1586,7 +1589,7 @@ struct status_data {
 		speed,
 		amotion, adelay, dmotion,
 		mode;
-	short 
+	short
 		hit, flee, cri, flee2,
 		def2, mdef2,
 #ifdef RENEWAL_ASPD
@@ -1614,7 +1617,7 @@ struct regen_data_sub {
 	struct {
 		unsigned int hp,sp;
 	} tick;
-	
+
 	//Regen rates (where every 1 means +100% regen)
 	struct {
 		unsigned char hp,sp;
@@ -1631,13 +1634,13 @@ struct regen_data {
 	struct {
 		unsigned int hp,sp,shp,ssp;
 	} tick;
-	
+
 	//Regen rates (where every 1 means +100% regen)
 	struct {
 		unsigned char
 		hp,sp,shp,ssp;
 	} rate;
-	
+
 	struct {
 		unsigned walk:1; //Can you regen even when walking?
 		unsigned gc:1;	//Tags when you should have double regen due to GVG castle

+ 4 - 2
tools/config.pl

@@ -29,7 +29,7 @@ use constant {
     MAX_PORT => 65535,
 };
 BEGIN { #check and install module
-    my @aCheckModule = ("DBI","DBD::mysql","YAML::XS","Cwd","Getopt::Long","Net::Ping");
+    my @aCheckModule = ("File::Basename","DBI","DBD::mysql","YAML","YAML::XS","Cwd","Getopt::Long","Net::Ping");
     my @aMarkInst = ();
     foreach(@aCheckModule) { eval "require $_" or push(@aMarkInst,$_); }
     CPAN::install("@aMarkInst") if(@aMarkInst > 0);
@@ -78,6 +78,8 @@ sub GetArgs {
 }
 
 sub Main {
+    my($filename, $dir, $suffix) = fileparse($0);
+    chdir $dir; #put ourself like was called in tools
     print "Welcome to athena config-tool\n";
     #default conf
     my %hDefConf = (    SERV_UID => "s1",
@@ -135,7 +137,7 @@ sub InstallSoft {
 	system("cd /usr/ports/databases/mysql55-server && make install clean");
 	#other utils ?
 	system("cd /usr/ports/www/wget && make install clean");
-	system("cd /usr/ports/archivers/unrar && make install clean")
+	system("cd /usr/ports/archivers/unrar && make install clean");
     }
 }