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

-Add Homon-S skills, 1st implementation (all done except Eleanors)
--Upd Skill conf to set land-limit for homonculus by default (ground skill limit)
--Mv MH_HEILIGE_STANGE and MH_ANGRIFFS_MODUS skill from Eleanor to Bayeri

-Enforce all zeny transaction to use pc_payzeny and pc_getzeny handlers, (auto log and clif)

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

glighta 12 лет назад
Родитель
Сommit
752776e4cc

+ 1 - 1
conf/battle/skill.conf

@@ -144,7 +144,7 @@ player_cloak_check_type: 1
 monster_cloak_check_type: 4
 
 // Can't place unlimited land skills at the same time (Note 3)
-land_skill_limit: 1
+land_skill_limit: 9
 
 //Determines which kind of skill-failed messages should be sent:
 // 1 - Disable all skill-failed messages.

+ 2 - 2
db/homun_skill_tree.txt

@@ -95,6 +95,8 @@
 6049,8031,5,0,0,0,0,0,0,0,0,0,0 	//MH_STAHL_HORN
 6049,8032,5,0,0,0,0,0,0,0,0,0,0 	//MH_GOLDENE_FERSE
 6049,8033,5,0,0,0,0,0,0,0,0,0,0 	//MH_STEINWAND
+6049,8034,5,0,0,0,0,0,0,0,0,0,0		//MH_HEILIGE_STANGE
+6049,8035,5,0,0,0,0,0,0,0,0,0,0		//MH_ANGRIFFS_MODUS
 //Sera
 6050,8018,5,0,0,0,0,0,0,0,0,0,0 	//MH_SUMMON_LEGION
 6050,8019,5,0,0,0,0,0,0,0,0,0,0 	//MH_NEEDLE_OF_PARALYZE
@@ -111,8 +113,6 @@
 6052,8028,5,0,0,0,0,0,0,0,0,0,0 	//MH_SONIC_CRAW
 6052,8029,5,0,0,0,0,0,0,0,0,0,0 	//MH_SILVERVEIN_RUSH
 6052,8030,5,0,0,0,0,0,0,0,0,0,0 	//MH_MIDNIGHT_FRENZY
-6052,8034,5,0,0,0,0,0,0,0,0,0,0 	//MH_HEILIGE_STANGE
-6052,8035,5,0,0,0,0,0,0,0,0,0,0 	//MH_ANGRIFFS_MODUS
 6052,8036,5,0,0,0,0,0,0,0,0,0,0 	//MH_TINDER_BREAKER
 6052,8037,5,0,0,0,0,0,0,0,0,0,0 	//MH_CBC
 6052,8038,5,0,0,0,0,0,0,0,0,0,0 	//MH_EQC

+ 18 - 18
db/re/skill_cast_db.txt

@@ -1722,23 +1722,23 @@
 //==========================================
 
 //-- MH_SUMMON_LEGION
-8018,2000,0,0,0,20000:30000:40000:50000:60000,0,400:600:800:1000:1200
+8018,1600:1400:1200:1000:800,0,0,20000:30000:40000:50000:60000,0,0,400:600:800:1000:1200
 //-- MH_NEEDLE_OF_PARALYZE 
-8019,1500,0,0,0,0,0,500:400:300:200:100
+8019,1000:1100:1200:1300:1400,0,0,12000:14000:16000:18000:20000,0,0,500:400:300:200:100
 //-- MH_POISON_MIST
-8020,1000:1200:1400:1600:1800,0,0,0,12000:14000:16000:18000:20000,0,500
+8020,500:700:900:1100:1300,0,0,12000:14000:16000:18000:20000,4000:6000:8000:10000:12000,0,500
 //-- MH_PAIN_KILLER
-8021,2000,0,0,0,20000:30000:40000:50000:60000,0,1000:800:600:400:200
+8021,1000:1200:1400:1600:1800,0,0,20000:30000:40000:50000:60000,0,0,1000:800:600:400:200
 //-- MH_LIGHT_OF_REGENE
-8022,1600:1400:1200:1000:800,0,0,0,360000:420000:480000:540000:600000,0,1600:1400:1200:1000:800
+8022,1600:1400:1200:1000:800,0,0,360000:420000:480000:540000:600000,0,0,1600:1400:1200:1000:800
 //-- MH_OVERED_BOOST
-8023,1000,0,0,0,30000:45000:60000:75000:90000,0,200:300:400:500:600
+8023,800:700:600:500:400,0,0,30000:45000:60000:75000:90000,0,0,200:300:400:500:600
 //-- MH_ERASER_CUTTER
-8024,1000:1500:2000:2500:3000,0,0,0,0,0,0
+8024,1000:1500:2000:2500:3000,0,0,0,0,0,-1
 //-- MH_XENO_SLASHER
-8025,2000:3000:4000:5000:6000,0,0,0,500,0,500
+8025,1500:2500:3500:4500:5500,0,0,500,0,0,500
 //-- MH_SILENT_BREEZE
-8026,2000,0,0,0,9000:12000:15000:18000:21000,0,1000:800:600:400:200
+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
 //-- MH_SONIC_CRAW
@@ -1748,15 +1748,15 @@
 //-- MH_MIDNIGHT_FRENZY
 //8030,0,0,0,0,0,0,0
 //-- MH_STAHL_HORN 
-8031,1000,0,0,0,0,0,200:400:600:800:1000
+8031,800:600:400:200:0,0,0,5000,0,0,200:400:600:800:1000
 //-- MH_GOLDENE_FERSE
-8032,1000:1200:1400:1600:1800,0,0,0,30000:45000:60000:75000:90000,0,0
+8032,1000:1200:1400:1600:1800,0,0,30000:45000:60000:75000:90000,0,0,-1
 //-- MH_STEINWAND
-8033,1000,0,0,0,30000:45000:60000:75000:90000,0,0
+8033,1000,0,0,30000:45000:60000:75000:90000,0,0,-1
 //-- MH_HEILIGE_STANGE
 8034,2000,0,0,0,0,0,1800:1600:1400:1200:1000
 //-- MH_ANGRIFFS_MODUS
-8035,200:400:600:800:1000,0,0,0,30000:45000:60000:75000:90000,0,0
+8035,200:400:600:800:1000,0,0,30000:45000:60000:75000:90000,0,0,-1
 //-- MH_TINDER_BREAKER
 //8036,0,0,0,0,0,0,0
 //-- MH_CBC
@@ -1764,15 +1764,15 @@
 //-- MH_EQC
 //8038,0,0,0,0,0,0,0
 //-- MH_MAGMA_FLOW
-8039,4000,0,0,0,30000:45000:60000:75000:90000,0,2000:1500:1000:500:0
+8039,2000:2500:3000:3500:4000,0,0,30000:45000:60000:75000:90000,0,0,2000:1500:1000:500:-1
 //-- MH_GRANITIC_ARMOR
-8040,6000:5500:5000:4500:4000,0,0,0,0,0,1000
+8040,6000:5500:5000:4500:4000,0,0,60000,0,0,1000
 //-- MH_LAVA_SLIDE
-8041,6000:5500:5000:4500:4000,0,0,0,12000:14000:16000:18000:20000,0,1000
+8041,6000:5500:5000:4500:4000,0,0,12000:14000:16000:18000:20000,0,0,1000
 //-- MH_PYROCLASTIC
-8042,6000:5500:5000:4500:4000,0,0,0,60000:90000:120000:150000:180000,0,1000
+8042,5000:4500:4000:3500:3000,0,0,60000:90000:120000:150000:180000,0,0,1000
 //-- MH_VOLCANIC_ASH
-8043,5000:4500:4000:3500:3000,0,0,0,12000:14000:16000:18000:20000,0,1000
+8043,5000:4500:4000:3500:3000,0,0,12000:14000:16000:18000:20000,0,0,1000
 
 //===== Mercenary Skills ===================
 //-- MS_MAGNUM

+ 7 - 7
db/re/skill_db.txt

@@ -1075,30 +1075,30 @@
 8015,0,0,0,0,0x1,0,5,0,no,0,0,0,none,0,		HVAN_INSTRUCT,Instruct
 8016,4,6,4,-1,0xD2,4,3,1,no,0,0,0,misc,0,	HVAN_EXPLOSION,Bio Explosion
 //
-8018,9,6,1,0,0x1,0,5,1,no,0,0,0,none,0,		MH_SUMMON_LEGION,Summon Legion
+8018,9,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_SUMMON_LEGION,Summon Legion
 8019,5,6,1,5,0,0,5,1,no,0,0,0,weapon,0,		MH_NEEDLE_OF_PARALYZE,Needle of Paralyze
-8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,		MH_POISON_MIST,Nevoa Venenosa
+8020,5,6,2,5,0,0,5,1,no,0,0,1,weapon,0,		MH_POISON_MIST,Poison Mist
 8021,1,6,1,0,0x1,0,5,1,no,0,0,0,none,0,		MH_PAIN_KILLER,Pain Killer
 8022,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,		MH_LIGHT_OF_REGENE,Light of Regene
 8023,0,6,4,0,0,0x1,5,1,no,0,0,0,none,0,		MH_OVERED_BOOST,Overed Boost
-8024,7,6,1,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0,	MH_ERASER_CUTTER,Corte Ilusório
+8024,7,6,1,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0,	MH_ERASER_CUTTER,Eraser Cutter
 8025,7,6,2,4:0:4:0:4,0,0,5,1,no,0,0,0,magic,0,	MH_XENO_SLASHER,Xeno Slasher
 8026,5:5:7:7:9,6,16,0,0x1,0,5,1,no,0,0,0,magic,0,	MH_SILENT_BREEZE,Silent Breeze
 8027,0,6,4,0,0x1,0,1,1,no,0,0,0,none,0,		MH_STYLE_CHANGE,Style Change
 8028,1,8,1,0,0,0,5,1,no,0,0,0,weapon,0,		MH_SONIC_CRAW,Sonic Claw
 8029,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0,	MH_SILVERVEIN_RUSH,Silver Bain Rush
 8030,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0,	MH_MIDNIGHT_FRENZY,Midnight Frenzy
-8031,5:6:7:8:9,6,1,0,0,0,5,1,no,0,0,0,weapon,3,	MH_STAHL_HORN,Chifre de Aço
-8032,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_GOLDENE_FERSE,Ferraduras de Ouro
+8031,5:6:7:8:9,6,1,0,0,0,5,1,no,0,0,0,weapon,3,	MH_STAHL_HORN,Steel Horn
+8032,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_GOLDENE_FERSE,Golden Heel
 8033,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_STEINWAND,Stone Wall
 8034,9,6,1,6,0x2,1:1:1:1:2,5,1,no,0,0,0,magic,0,	MH_HEILIGE_STANGE,Holy Pole
-8035,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_ANGRIFFS_MODUS,Modo de Ataque
+8035,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_ANGRIFFS_MODUS,Attack Mode
 8036,3:4:5:6:7,6,1,0,0,0,5,1,no,0,0,0,weapon,0,	MH_TINDER_BREAKER,Tinder Breaker
 8037,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0,	MH_CBC,Continual Break Combo
 8038,1,6,4,0,0,0,5,1,no,0,0x200,0,weapon,0,	MH_EQC,Eternal Quick Combo
 8039,0,6,4,3,0x2,1:1:1:2:2,5,1,no,0,0,0,weapon,0,	MH_MAGMA_FLOW,Magma Flow
 8040,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,		MH_GRANITIC_ARMOR,Granitic Armor
-8041,7,6,2,3,0x2,0,5,1,no,0,0,1,weapon,0,		MH_LAVA_SLIDE,Deslizamento de Lava
+8041,7,6,2,3,0x2,0,5,1,no,0,0,1,weapon,0,		MH_LAVA_SLIDE,Lava Slide
 8042,0,6,4,3,0x1,0,5,1,no,0,0,0,none,0,		MH_PYROCLASTIC,Pyroclastic
 8043,7,6,2,0,0x1,0,5,1,no,0,0,3,none,0,		MH_VOLCANIC_ASH,Volcanic Ash
 

+ 2 - 2
db/re/skill_unit_db.txt

@@ -163,8 +163,8 @@
 8020,0xf5,    ,  0, 3,2300:2100:1900:1700:1500,enemy,   0x018	//MH_POISON_MIST
 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,1000,enemy,   0x018	//MH_LAVA_SLIDE
-8043,0xf7,    ,  0, 1,1000,enemy,   0x018	//MH_VOLCANIC_ASH
+8041,0xf6,    ,  1:1:2:2:3, 0,2000,enemy,   0x01A	//MH_LAVA_SLIDE
+8043,0xf7,    ,  1, 0,-1,enemy,   0x2018	//MH_VOLCANIC_ASH
 
 8208,0x86,    ,  0, 2,1000,enemy, 0x080	//MA_SHOWER
 8209,0x90,    ,  0, 1,1000,enemy, 0x006	//MA_SKIDTRAP

+ 3 - 21
src/map/atcommand.c

@@ -2196,7 +2196,7 @@ ACMD_FUNC(killmonster)
 		if ((map_id = map_mapname2mapid(map_name)) < 0)
 			map_id = sd->bl.m;
 	}
-	
+
 	drop_flag = strcmp(command+1, "killmonster2");
 
 	map_foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag);
@@ -2533,25 +2533,7 @@ ACMD_FUNC(zeny)
 		clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>).
 		return -1;
 	}
-
-	new_zeny = sd->status.zeny + zeny;
-	if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY)) // fix positiv overflow
-		new_zeny = MAX_ZENY;
-	else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0)) // fix negativ overflow
-		new_zeny = 0;
-
-	if (new_zeny != sd->status.zeny) {
-		sd->status.zeny = new_zeny;
-		clif_updatestatus(sd, SP_ZENY);
-		clif_displaymessage(fd, msg_txt(176)); // Current amount of zeny changed.
-	} else {
-		if (zeny < 0)
-			clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value.
-		else
-			clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value.
-		return -1;
-	}
-
+	pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL);
 	return 0;
 }
 
@@ -3393,7 +3375,7 @@ ACMD_FUNC(spiritball)
 	if( sd->spiritball > 0 )
 		pc_delspiritball(sd, sd->spiritball, 1);
 	sd->spiritball = number;
-	clif_spiritball(sd);
+	clif_spiritball(&sd->bl);
 	// no message, player can look the difference
 
 	return 0;

+ 61 - 7
src/map/battle.c

@@ -367,6 +367,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
                         if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB)
                                 status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
                         if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
+						if( tsc->data[SC_ASH]) damage += damage/2; //150%
                         break;
                 case ELE_HOLY:
                         if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
@@ -482,7 +483,14 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 		if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT )
 		{
 			struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
+			int skill_id = sc->data[SC_SAFETYWALL]->val2;
 			if (group) {
+				if(skill_id == MH_STEINWAND){
+				    if (--group->val2<=0)
+					    skill_delunitgroup(group);
+				    d->dmg_lv = ATK_BLOCK;
+				    return 0;
+				}
 				/**
 				 * in RE, SW possesses a lifetime equal to 3 times the caster's health
 				 **/
@@ -730,6 +738,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			//Reduction: 6% + 6% every 20%
 			damage -= damage * 6 * (1+per) / 100;
 		}
+		if(sc->data[SC_GRANITIC_ARMOR]){
+			damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2/100;
+		}
+		if(sc->data[SC_PAIN_KILLER]){
+			damage -= damage * sc->data[SC_PAIN_KILLER]->val3/100;
+		}
+		if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){
+			skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0);
+		}
+
 /**
  * In renewal steel body reduces all incoming damage by 1/10
  **/
@@ -787,6 +805,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 
 		if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 )
 			pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
+		if (sc->data[SC_STYLE_CHANGE] && rnd() % 100 < 50) {
+            TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+            if (hd) hom_addspiritball(hd, 10); //add a sphere
+        }
 
 		if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
 			status_change_spread(bl, src); // Deadly infect attacked side
@@ -846,6 +868,10 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
 			sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1));
 		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() % 100 < 50) {
+            TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+            if (hd) hom_addspiritball(hd, 10);
+        }
 	}
 
 	if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp)
@@ -1480,6 +1506,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 			break;
 	}
 
+	if (!(nk & NK_NO_ELEFIX) && !n_ele)
+	    if (src->type == BL_HOM)
+		n_ele = true; //skill is "not elemental"
+	if (sc && sc->data[SC_GOLDENE_FERSE] && ((!skill_num && (rnd() % 100 < sc->data[SC_GOLDENE_FERSE]->val4)) || skill_num == MH_STAHL_HORN)) {
+	    s_ele = s_ele_ = ELE_HOLY;
+	    n_ele = false;
+	}
+
 	if(!skill_num)
   	{	//Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
 		if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
@@ -1818,7 +1852,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				skillratio += sc->data[SC_OVERTHRUST]->val3;
 			if(sc->data[SC_MAXOVERTHRUST])
 				skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
-			if(sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST])
+			if (sc->data[SC_BERSERK] || sc->data[SC_SATURDAYNIGHTFEVER] || sc->data[SC__BLOODYLUST])
 				skillratio += 100;
 			if(sc->data[SC_ZENKAI] && sstatus->rhw.ele == sc->data[SC_ZENKAI]->val2 )
 				skillratio += sc->data[SC_ZENKAI]->val1 * 2;
@@ -2564,12 +2598,18 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 				case KO_BAKURETSU:
 					skillratio = 50 * skill_lv * (sd?pc_checkskill(sd,NJ_TOBIDOUGU):10);
 					break;
+				case MH_NEEDLE_OF_PARALYZE:
+					skillratio += 600 + 100 * skill_lv;
+					break;
 				case MH_STAHL_HORN:
-					skillratio += 500 + 100 * skill_lv;
+					skillratio += 400 + 100 * skill_lv;
 					break;
 				case MH_LAVA_SLIDE:
 					skillratio = 70 * skill_lv;
 					break;
+				case MH_MAGMA_FLOW:
+					skillratio += -100 + 100 * skill_lv;
+					break;
 			}
 
 			ATK_RATE(skillratio);
@@ -2686,6 +2726,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
 						ATK_ADDRATE(sc->data[SC_EDP]->val3);
 				}
 			}
+			if(sc->data[SC_STYLE_CHANGE]){
+                TBL_HOM *hd = BL_CAST(BL_HOM,src);
+                if (hd) ATK_ADD(hd->spiritball * 3);
+            }
+
 		}
 
 		switch (skill_num) {
@@ -3890,10 +3935,19 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 						skillratio += 1100;
 						break;
 					case MH_ERASER_CUTTER:
-						if (skill_lv >= 3)
-							skillratio += 800 + 200 * skill_lv ;
-						else
-							skillratio += 500 + 400 * skill_lv;
+						if(skill_lv%2) skillratio += 400; //600:800:1000
+						else skillratio += 700; //1000:1200
+						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;
+					case MH_HEILIGE_STANGE:
+					    skillratio += 400 + 250 * skill_lv;
+					    break;
+					case MH_POISON_MIST:
+					    skillratio += 100 * skill_lv;
 						break;
 				}
 
@@ -4403,7 +4457,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 			if( sd ) {
 				if ( md.damage > sd->status.zeny )
 					md.damage = sd->status.zeny;
-				pc_payzeny(sd, md.damage);
+				pc_payzeny(sd, md.damage,LOG_TYPE_STEAL,NULL);
 			}
 		break;
 	}

+ 2 - 5
src/map/buyingstore.c

@@ -366,17 +366,14 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
 		ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid );
 		zeny = amount*pl_sd->buyingstore.items[listidx].price;
 
-		// log
-		log_zeny(sd, LOG_TYPE_BUYING_STORE, pl_sd, zeny);
-
 		// move item
 		pc_additem(pl_sd, &sd->status.inventory[index], amount, LOG_TYPE_BUYING_STORE);
 		pc_delitem(sd, index, amount, 1, 0, LOG_TYPE_BUYING_STORE);
 		pl_sd->buyingstore.items[listidx].amount-= amount;
 
 		// pay up
-		pc_payzeny(pl_sd, zeny);
-		pc_getzeny(sd, zeny);
+		pc_payzeny(pl_sd, zeny, LOG_TYPE_BUYING_STORE, sd);
+		pc_getzeny(sd, zeny, LOG_TYPE_BUYING_STORE, pl_sd);
 		pl_sd->buyingstore.zenylimit-= zeny;
 
 		// notify clients

+ 30 - 25
src/map/clif.c

@@ -1356,7 +1356,7 @@ int clif_spawn(struct block_list *bl)
 			TBL_PC *sd = ((TBL_PC*)bl);
 			int i;
 			if (sd->spiritball > 0)
-				clif_spiritball(sd);
+				clif_spiritball(&sd->bl);
 			if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
 				clif_specialeffect(bl,423,AREA);
 			else if(sd->state.size==SZ_MEDIUM)
@@ -5440,12 +5440,12 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
 	char buf[100];
 	int len;
 	nullpo_retv(bl);
-	
+
 	if(!message)
 		return;
-	
+
 	len = strlen(message)+1;
-	
+
 	if( len > sizeof(buf)-8 ) {
 		ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
 		len = sizeof(buf)-8;
@@ -5465,7 +5465,7 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) {
 void clif_MainChatMessage(const char* message) {
 	uint8 buf[200];
 	int len;
-	
+
 	if(!message)
 		return;
 
@@ -6896,20 +6896,27 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
 		clif_send(buf, packet_len(0x1cf), src, AREA);
 }
 
-
-/// Notifies clients in an area of an object's spirits.
-/// 01d0 <id>.L <amount>.W (ZC_SPIRITS)
-/// 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
-void clif_spiritball(struct map_session_data *sd)
-{
-	unsigned char buf[8];
-
-	nullpo_retv(sd);
-
-	WBUFW(buf,0)=0x1d0;
-	WBUFL(buf,2)=sd->bl.id;
-	WBUFW(buf,6)=sd->spiritball;
-	clif_send(buf,packet_len(0x1d0),&sd->bl,AREA);
+/*==========================================
+ * Server tells clients nearby 'sd' (and himself) to display 'sd->spiritball' number of spiritballs on 'sd'
+ * Notifies clients in an area of an object's spirits.
+ * 01d0 <id>.L <amount>.W (ZC_SPIRITS)
+ * 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
+ *------------------------------------------*/
+void clif_spiritball(struct block_list *bl) {
+    unsigned char buf[16];
+    TBL_PC *sd = BL_CAST(BL_PC,bl);
+    TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+
+    nullpo_retv(bl);
+
+    WBUFW(buf, 0) = 0x1d0;
+    WBUFL(buf, 2) = bl->id;
+	WBUFW(buf, 6) = 0; //init to 0
+    switch(bl->type){
+        case BL_PC: WBUFW(buf, 6) = sd->spiritball; break;
+        case BL_HOM: WBUFW(buf, 6) = hd->spiritball; break;
+    }
+    clif_send(buf, packet_len(0x1d0), bl, AREA);
 }
 
 
@@ -8205,7 +8212,7 @@ void clif_message(struct block_list* bl, const char* msg) {
 	unsigned short msg_len = strlen(msg) + 1;
 	uint8 buf[256];
 	nullpo_retv(bl);
-	
+
 	if( msg_len > sizeof(buf)-8 ) {
 		ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
 		msg_len = sizeof(buf)-8;
@@ -8215,7 +8222,7 @@ void clif_message(struct block_list* bl, const char* msg) {
 	WBUFW(buf,2) = msg_len + 8;
 	WBUFL(buf,4) = bl->id;
 	safestrncpy((char*)WBUFP(buf,8), msg, msg_len);
-	
+
 	clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
 }
 
@@ -14220,8 +14227,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
 		pc_delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION);
 		sd->auction.amount = 0;
 
-		log_zeny(sd, LOG_TYPE_AUCTION, sd, -zeny);
-		pc_payzeny(sd, zeny);
+		pc_payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL);
 	}
 }
 
@@ -14265,8 +14271,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd)
 	else if ( CheckForCharServer() ) // char server is down (bugreport:1138)
 		clif_Auction_message(fd, 0); // You have failed to bid into the auction
 	else {
-		log_zeny(sd, LOG_TYPE_AUCTION, sd, -bid);
-		pc_payzeny(sd, bid);
+		pc_payzeny(sd, bid, LOG_TYPE_AUCTION, NULL);
 		intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid);
 	}
 }

+ 1 - 1
src/map/clif.h

@@ -454,7 +454,7 @@ void clif_skillunit_update(struct block_list* bl);
 
 void clif_autospell(struct map_session_data *sd,int skilllv);
 void clif_devotion(struct block_list *src, struct map_session_data *tsd);
-void clif_spiritball(struct map_session_data *sd);
+void clif_spiritball(struct block_list *bl);
 void clif_combo_delay(struct block_list *bl,int wait);
 void clif_bladestop(struct block_list *src, int dst_id, int active);
 void clif_changemapcell(int fd, int m, int x, int y, int type, enum send_target target);

+ 1 - 1
src/map/guild.c

@@ -408,7 +408,7 @@ int guild_created(int account_id,int guild_id)
 	sd->status.guild_id=guild_id;
 	clif_guild_created(sd,0);
 	if(battle_config.guild_emperium_check)
-		pc_delitem(sd,pc_search_inventory(sd,714),1,0,0,LOG_TYPE_CONSUME);	// �G���y���E������
+		pc_delitem(sd,pc_search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME);	//emperium consumption
 	return 0;
 }
 

+ 40 - 0
src/map/homunculus.c

@@ -81,6 +81,46 @@ int hom_class2mapid(int hom_class)
 	}
 }
 
+int hom_addspiritball(TBL_HOM *hd, int max) {
+    nullpo_ret(hd);
+
+    if (max > MAX_SKILL_LEVEL)
+        max = MAX_SKILL_LEVEL;
+    if (hd->spiritball < 0)
+        hd->spiritball = 0;
+
+    if (hd->spiritball && hd->spiritball >= max) {
+        hd->spiritball = max;    
+    }
+    else
+        hd->spiritball++;
+ 
+    clif_spiritball(&hd->bl);
+
+    return 0;
+}
+
+int hom_delspiritball(TBL_HOM *hd, int count, int type) {
+    nullpo_ret(hd);
+
+    if (hd->spiritball <= 0) {
+        hd->spiritball = 0;
+        return 0;
+    }
+    if (count <= 0)
+        return 0;
+    if (count > MAX_SKILL_LEVEL)
+        count = MAX_SKILL_LEVEL;
+    if (count > hd->spiritball)
+        count = hd->spiritball;
+    
+    hd->spiritball -= count;
+    if (!type)
+        clif_spiritball(&hd->bl);
+
+    return 0;
+}
+
 void merc_damage(struct homun_data *hd) {
 	clif_hominfo(hd->master,hd,0);
 }

+ 5 - 0
src/map/homunculus.h

@@ -45,6 +45,8 @@ struct homun_data {
 	int hungry_timer;	//[orn]
 	unsigned int exp_next;
 	char blockskill[MAX_SKILL];	// [orn]
+    
+    int spiritball; //for homun S [lighta]
 };
 
 #define HOM_EVO 0x100 //256
@@ -112,4 +114,7 @@ void merc_hom_init_timers(struct homun_data * hd);
 void merc_skill_reload(void);
 void merc_reload(void);
 
+int hom_addspiritball(TBL_HOM *hd, int max);
+int hom_delspiritball(TBL_HOM *hd, int count, int type);
+
 #endif /* _HOMUNCULUS_H_ */

+ 32 - 34
src/map/intif.c

@@ -50,7 +50,7 @@ extern int char_fd; // inter server Fd used for char_fd
 #define inter_fd char_fd	// alias
 
 //-----------------------------------------------------------------
-// Send to inter server 
+// Send to inter server
 
 int CheckForCharServer(void)
 {
@@ -417,7 +417,7 @@ int intif_request_partyinfo(int party_id, int char_id)
 	return 0;
 }
 
-// Request to add a member to party 
+// Request to add a member to party
 int intif_party_addmember(int party_id,struct party_member *member)
 {
 	if (CheckForCharServer())
@@ -460,11 +460,11 @@ int intif_party_leave(int party_id,int account_id, int char_id)
 	return 0;
 }
 
-// Request keeping party for new map ?? 
+// Request keeping party for new map ??
 int intif_party_changemap(struct map_session_data *sd,int online)
 {
 	int m, mapindex;
-	
+
 	if (CheckForCharServer())
 		return 0;
 	if(!sd)
@@ -487,7 +487,7 @@ int intif_party_changemap(struct map_session_data *sd,int online)
 	return 1;
 }
 
-// Request breaking party 
+// Request breaking party
 int intif_break_party(int party_id)
 {
 	if (CheckForCharServer())
@@ -687,7 +687,7 @@ int intif_guild_change_memberinfo(int guild_id,int account_id,int char_id,
 	return 0;
 }
 
-// Request a change of Guild title 
+// Request a change of Guild title
 int intif_guild_position(int guild_id,int idx,struct guild_position *p)
 {
 	if (CheckForCharServer())
@@ -702,7 +702,7 @@ int intif_guild_position(int guild_id,int idx,struct guild_position *p)
 	return 0;
 }
 
-// Request an update of Guildskill skillnum 
+// Request an update of Guildskill skillnum
 int intif_guild_skillup(int guild_id, int skill_num, int account_id, int max)
 {
 	if( CheckForCharServer() )
@@ -857,7 +857,7 @@ int intif_homunculus_requestdelete(int homun_id)
 
 // Wisp/Page reception // rewritten by [Yor]
 int intif_parse_WisMessage(int fd)
-{ 
+{
 	struct map_session_data* sd;
 	char *wisp_source;
 	char name[NAME_LENGTH];
@@ -881,7 +881,7 @@ int intif_parse_WisMessage(int fd)
 		sd->ignore[i].name[0] != '\0' &&
 		strcmp(sd->ignore[i].name, wisp_source) != 0
 		; i++);
-	
+
 	if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0')
 	{	//Ignored
 		intif_wis_replay(id, 2);
@@ -913,7 +913,7 @@ static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va)
 	char *wisp_name;
 	char *message;
 	int len;
-	
+
 	if (!pc_has_permission(sd, permission))
 		return 0;
 	wisp_name = va_arg(va, char*);
@@ -1006,7 +1006,7 @@ int intif_parse_LoadGuildStorage(int fd)
 	struct guild_storage *gstor;
 	struct map_session_data *sd;
 	int guild_id;
-	
+
 	guild_id = RFIFOL(fd,8);
 	if(guild_id <= 0)
 		return 1;
@@ -1426,7 +1426,7 @@ int intif_parse_questlog(int fd)
 		sd->quest_index[i] = quest_search_db(sd->quest_log[i].quest_id);
 
 		if( sd->quest_index[i] < 0 )
-		{  
+		{
 			ShowError("intif_parse_questlog: quest %d not found in DB.\n",sd->quest_log[i].quest_id);
 			sd->avail_quests--;
 			sd->num_quests--;
@@ -1786,7 +1786,7 @@ static void intif_parse_Auction_results(int fd)
 int intif_Auction_register(struct auction_data *auction)
 {
 	int len = sizeof(struct auction_data) + 4;
-	
+
 	if( CheckForCharServer() )
 		return 0;
 
@@ -1795,7 +1795,7 @@ int intif_Auction_register(struct auction_data *auction)
 	WFIFOW(inter_fd,2) = len;
 	memcpy(WFIFOP(inter_fd,4), auction, sizeof(struct auction_data));
 	WFIFOSET(inter_fd,len);
-	
+
 	return 1;
 }
 
@@ -1827,8 +1827,7 @@ static void intif_parse_Auction_register(int fd)
 		clif_Auction_message(sd->fd, 4);
 		pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION);
 
-		log_zeny(sd, LOG_TYPE_AUCTION, sd, zeny);
-		pc_getzeny(sd, zeny);
+		pc_getzeny(sd, zeny, LOG_TYPE_AUCTION,NULL);
 	}
 }
 
@@ -1925,8 +1924,7 @@ static void intif_parse_Auction_bid(int fd)
 	clif_Auction_message(sd->fd, result);
 	if( bid > 0 )
 	{
-		log_zeny(sd, LOG_TYPE_AUCTION, sd, bid);
-		pc_getzeny(sd, bid);
+		pc_getzeny(sd, bid, LOG_TYPE_AUCTION,NULL);
 	}
 	if( result == 1 )
 	{ // To update the list, display your buy list
@@ -2041,10 +2039,10 @@ int intif_parse_mercenary_saved(int fd)
 int intif_elemental_create(struct s_elemental *ele)
 {
 	int size = sizeof(struct s_elemental) + 4;
-	
+
 	if( CheckForCharServer() )
 		return 0;
-	
+
 	WFIFOHEAD(inter_fd,size);
 	WFIFOW(inter_fd,0) = 0x307c;
 	WFIFOW(inter_fd,2) = size;
@@ -2062,7 +2060,7 @@ int intif_parse_elemental_received(int fd)
 			ShowError("intif: create elemental data size error %d != %d\n", sizeof(struct s_elemental), len);
 		return 0;
 	}
-	
+
 	elemental_data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4));
 	return 0;
 }
@@ -2071,7 +2069,7 @@ int intif_elemental_request(int ele_id, int char_id)
 {
 	if (CheckForCharServer())
 		return 0;
-	
+
 	WFIFOHEAD(inter_fd,10);
 	WFIFOW(inter_fd,0) = 0x307d;
 	WFIFOL(inter_fd,2) = ele_id;
@@ -2084,7 +2082,7 @@ int intif_elemental_delete(int ele_id)
 {
 	if (CheckForCharServer())
 		return 0;
-	
+
 	WFIFOHEAD(inter_fd,6);
 	WFIFOW(inter_fd,0) = 0x307e;
 	WFIFOL(inter_fd,2) = ele_id;
@@ -2096,17 +2094,17 @@ int intif_parse_elemental_deleted(int fd)
 {
 	if( RFIFOB(fd,2) != 1 )
 		ShowError("Elemental data delete failure\n");
-	
+
 	return 0;
 }
 
 int intif_elemental_save(struct s_elemental *ele)
 {
 	int size = sizeof(struct s_elemental) + 4;
-	
+
 	if( CheckForCharServer() )
 		return 0;
-	
+
 	WFIFOHEAD(inter_fd,size);
 	WFIFOW(inter_fd,0) = 0x307f;
 	WFIFOW(inter_fd,2) = size;
@@ -2119,7 +2117,7 @@ int intif_parse_elemental_saved(int fd)
 {
 	if( RFIFOB(fd,2) != 1 )
 		ShowError("Elemental data save failure\n");
-	
+
 	return 0;
 }
 
@@ -2127,18 +2125,18 @@ void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ) {
 
 
 	WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
-	
+
 	WFIFOW(inter_fd,0) = 0x3007;
 	WFIFOL(inter_fd,2) = u_fd;
 	WFIFOL(inter_fd,6) = aid;
 	WFIFOL(inter_fd,10) = group_id;
 	safestrncpy(WFIFOP(inter_fd,14), query, NAME_LENGTH);
-	
+
 	WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
-	
+
 	return;
 }
-	
+
 void intif_parse_MessageToFD(int fd) {
 	int u_fd = RFIFOL(fd,4);
 
@@ -2151,9 +2149,9 @@ void intif_parse_MessageToFD(int fd) {
 			safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12);
 			clif_displaymessage(u_fd,msg);
 		}
-	
+
 	}
-	
+
 	return;
 }
 
@@ -2250,7 +2248,7 @@ int intif_parse(int fd)
 	case 0x387c:	intif_parse_elemental_received(fd); break;
 	case 0x387d:	intif_parse_elemental_deleted(fd); break;
 	case 0x387e:	intif_parse_elemental_saved(fd); break;
-			
+
 	case 0x3880:	intif_parse_CreatePet(fd); break;
 	case 0x3881:	intif_parse_RecvPetData(fd); break;
 	case 0x3882:	intif_parse_SavePetOk(fd); break;

+ 8 - 15
src/map/mail.c

@@ -48,9 +48,7 @@ int mail_removezeny(struct map_session_data *sd, short flag)
 
 	if (flag && sd->mail.zeny > 0)
 	{  //Zeny send
-		log_zeny(sd, LOG_TYPE_MAIL, sd, -sd->mail.zeny);
-
-		sd->status.zeny -= sd->mail.zeny;
+		pc_payzeny(sd,sd->mail.zeny,LOG_TYPE_MAIL, NULL);
 	}
 	sd->mail.zeny = 0;
 	clif_updatestatus(sd, SP_ZENY);
@@ -59,10 +57,10 @@ int mail_removezeny(struct map_session_data *sd, short flag)
 }
 
 unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
-	
+
 	if( pc_istrading(sd) )
 		return 1;
-	
+
 	if( idx == 0 ) { // Zeny Transfer
 		if( amount < 0 || !pc_can_give_items(sd) )
 			return 1;
@@ -88,7 +86,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
 		sd->mail.index = idx;
 		sd->mail.nameid = sd->status.inventory[idx].nameid;
 		sd->mail.amount = amount;
-		
+
 		return 0;
 	}
 }
@@ -96,7 +94,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) {
 bool mail_setattachment(struct map_session_data *sd, struct mail_message *msg)
 {
 	int n;
-	
+
 	nullpo_retr(false,sd);
 	nullpo_retr(false,msg);
 
@@ -140,8 +138,7 @@ void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item
 
 	if( zeny > 0 )
 	{  //Zeny receive
-		log_zeny(sd, LOG_TYPE_MAIL, sd, zeny);
-		pc_getzeny(sd, zeny);
+		pc_getzeny(sd, zeny,LOG_TYPE_MAIL, NULL);
 	}
 }
 
@@ -170,13 +167,9 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg)
 
 	if( msg->zeny > 0 )
 	{
-		//Zeny receive (due to failure)
-		log_zeny(sd, LOG_TYPE_MAIL, sd, msg->zeny);
-
-		sd->status.zeny += msg->zeny;
-		clif_updatestatus(sd, SP_ZENY);
+		pc_getzeny(sd,msg->zeny,LOG_TYPE_MAIL, NULL); //Zeny receive (due to failure)
 	}
-	
+
 	clif_Mail_send(sd->fd, true);
 }
 

+ 2 - 2
src/map/mob.c

@@ -2290,7 +2290,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 				}
 			}
 			if(zeny) // zeny from mobs [Valaris]
-				pc_getzeny(tmpsd[i], zeny);
+				pc_getzeny(tmpsd[i], zeny, LOG_TYPE_PICKDROP_MONSTER, NULL);
 		}
 	}
 
@@ -2430,7 +2430,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 			if( sd->bonus.get_zeny_num && rnd()%100 < sd->bonus.get_zeny_rate ) {
 				i = sd->bonus.get_zeny_num > 0 ? sd->bonus.get_zeny_num : -md->level * sd->bonus.get_zeny_num;
 				if (!i) i = 1;
-				pc_getzeny(sd, 1+rnd()%i);
+				pc_getzeny(sd, 1+rnd()%i, LOG_TYPE_OTHER, NULL);
 			}
 		}
 

+ 66 - 74
src/map/npc.c

@@ -199,7 +199,7 @@ int npc_enable(const char* name, int flag)
 	} else
 		clif_changeoption(&nd->bl);
 
-	if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) 	//check if player standing on a OnTouchArea	
+	if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) 	//check if player standing on a OnTouchArea
 		map_foreachinarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd );
 
 	return 0;
@@ -302,7 +302,7 @@ int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char
 
 /**
  * Exec name (NPC events) on player or global
- * Do on all NPC when called with foreach 
+ * Do on all NPC when called with foreach
  * @see DBApply
  */
 int npc_event_doall_sub(DBKey key, DBData *data, va_list ap)
@@ -411,22 +411,22 @@ int npc_event_do_clock(int tid, unsigned int tick, int id, intptr_t data)
 			case 6: day = "Sat"; break;
 			default:day = ""; break;
 		}
-		
+
 		sprintf(buf,"OnMinute%02d",t->tm_min);
 		c += npc_event_doall(buf);
-		
+
 		sprintf(buf,"OnClock%02d%02d",t->tm_hour,t->tm_min);
 		c += npc_event_doall(buf);
-		
+
 		sprintf(buf,"On%s%02d%02d",day,t->tm_hour,t->tm_min);
 		c += npc_event_doall(buf);
 	}
-	
+
 	if (t->tm_hour != ev_tm_b.tm_hour) {
 		sprintf(buf,"OnHour%02d",t->tm_hour);
 		c += npc_event_doall(buf);
 	}
-	
+
 	if (t->tm_mday != ev_tm_b.tm_mday) {
 		sprintf(buf,"OnDay%02d%02d",t->tm_mon+1,t->tm_mday);
 		c += npc_event_doall(buf);
@@ -539,13 +539,13 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data)
 			sd->npc_timer_id = INVALID_TIMER;
 		else
 			nd->u.scr.timerid = INVALID_TIMER;
-		
+
 		ers_free(timer_event_ers, ted);
 	}
 
 	// Run the script
 	run_script(nd->u.scr.script,te->pos,nd->u.scr.rid,nd->bl.id);
-	
+
 	nd->u.scr.rid = old_rid; // Attached-rid should be restored anyway.
 	if( sd )
 	{ // Restore previous data, only if this timer is a player-attached one.
@@ -564,7 +564,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
 	unsigned int tick = gettick();
 	struct map_session_data *sd = NULL; //Player to whom script is attached.
 	struct timer_event_data *ted;
-		
+
 	nullpo_ret(nd);
 
 	// Check if there is an OnTimer Event
@@ -584,7 +584,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
 	}
 	else if( nd->u.scr.timerid != INVALID_TIMER || nd->u.scr.timertick )
 		return 0;
-	
+
 	if (j < nd->u.scr.timeramount)
 	{
 		// Arrange for the next event
@@ -606,7 +606,7 @@ int npc_timerevent_start(struct npc_data* nd, int rid)
 	}
 	else if (!sd)
 	{
-		nd->u.scr.timertick = tick; 
+		nd->u.scr.timertick = tick;
 	}
 
 	return 0;
@@ -627,7 +627,7 @@ int npc_timerevent_stop(struct npc_data* nd)
 		ShowError("npc_timerevent_stop: Attached player not found!\n");
 		return 1;
 	}
-	
+
 	tid = sd?&sd->npc_timer_id:&nd->u.scr.timerid;
 	if( *tid == INVALID_TIMER && (sd || !nd->u.scr.timertick) ) // Nothing to stop
 		return 0;
@@ -700,7 +700,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
 			nd->u.scr.rid = sd->bl.id;
 			nd->u.scr.timertick = gettick();
 			nd->u.scr.timer = ted->time;
-		
+
 			//Execute label
 			run_script(nd->u.scr.script,ev->pos,sd->bl.id,nd->bl.id);
 
@@ -855,7 +855,7 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
 	xs = nd->u.scr.xs;
 	ys = nd->u.scr.ys;
 
-	if( sd->bl.m != nd->bl.m || 
+	if( sd->bl.m != nd->bl.m ||
 		sd->bl.x < nd->bl.x - xs || sd->bl.x > nd->bl.x + xs ||
 		sd->bl.y < nd->bl.y - ys || sd->bl.y > nd->bl.y + ys ||
 		pc_ishiding(sd) || leavemap )
@@ -1012,7 +1012,7 @@ int npc_check_areanpc(int flag, int m, int x, int y, int range)
 	y0 = max(y-range, 0);
 	x1 = min(x+range, map[m].xs-1);
 	y1 = min(y+range, map[m].ys-1);
-	
+
 	//First check for npc_cells on the range given
 	i = 0;
 	for (ys = y0; ys <= y1 && !i; ys++) {
@@ -1106,7 +1106,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
 {
 	char buffer[200];
     char time[10];
-	
+
     strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
 
 	// TODO: Find exact color?
@@ -1117,7 +1117,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
 
     snprintf(buffer, sizeof(buffer), msg_txt(659), time);
     clif_scriptmes(sd, nd->bl.id, buffer);
-	
+
     clif_scriptmes(sd, nd->bl.id, msg_txt(660));
 
 	snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown");
@@ -1128,7 +1128,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd)
 
 /*==========================================
  * NPC 1st call when clicking on npc
- * Do specific action for NPC type (openshop, run scripts...) 
+ * Do specific action for NPC type (openshop, run scripts...)
  *------------------------------------------*/
 int npc_click(struct map_session_data* sd, struct npc_data* nd)
 {
@@ -1179,7 +1179,7 @@ int npc_scriptcont(struct map_session_data* sd, int id)
 		  	nd?(char*)nd->name:"'Unknown NPC'", (int)id);
 		return 1;
 	}
-	
+
 	if(id != fake_nd->bl.id) { // Not item script
 		if ((npc_checknear(sd,map_id2bl(id))) == NULL){
 			ShowWarning("npc_scriptcont: failed npc_checknear test.\n");
@@ -1218,7 +1218,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type)
 
 	if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL)
 		return 1;
-	
+
 	if (nd->subtype!=SHOP) {
 		ShowError("no such shop npc : %d\n",id);
 		if (sd->npc_id == id)
@@ -1459,7 +1459,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
 		int nameid, amount, value;
 
 		// find this entry in the shop's sell list
-		ARR_FIND( 0, nd->u.shop.count, j, 
+		ARR_FIND( 0, nd->u.shop.count, j,
 			item_list[i*2+1] == nd->u.shop.shop_item[j].nameid || //Normal items
 			item_list[i*2+1] == itemdb_viewid(nd->u.shop.shop_item[j].nameid) //item_avail replacement
 		);
@@ -1515,11 +1515,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list)
 	if( pc_inventoryblank(sd) < new_ )
 		return 3;	// Not enough space to store items
 
-	//Logs (S)hopping Zeny [Lupus]
-	log_zeny(sd, LOG_TYPE_NPC, sd, -(int)z);
-	//Logs
-
-	pc_payzeny(sd,(int)z);
+	pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
 
 	for( i = 0; i < n; ++i )
 	{
@@ -1584,7 +1580,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
 		snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
 		script_cleararray_pc(sd, card_slot, (void*)0);
 	}
-	
+
 	// save list of to be sold items
 	for( i = 0; i < n; i++ )
 	{
@@ -1598,7 +1594,7 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short*
 			script_setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine);
 			script_setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute);
 			script_setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify);
-		
+
 			for( j = 0; j < MAX_SLOTS; j++ )
 			{// store each of the cards from the equipment in the array
 				snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1);
@@ -1691,11 +1687,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list)
 	if( z > MAX_ZENY )
 		z = MAX_ZENY;
 
-	//Logs (S)hopping Zeny [Lupus]
-	log_zeny(sd, LOG_TYPE_NPC, sd, (int)z);
-	//Logs
-
-	pc_getzeny(sd, (int)z);
+	pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL);
 
 	// custom merchant shop exp bonus
 	if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0)
@@ -1793,13 +1785,13 @@ int npc_unload(struct npc_data* nd, bool single) {
 		if( nd->path && nd->path != npc_last_ref ) {
 			npd = strdb_get(npc_path_db, nd->path);
 		}
-		
+
 		if( npd && --npd->references == 0 ) {
 			strdb_remove(npc_path_db, nd->path);/* remove from db */
 			aFree(nd->path);/* remove now that no other instances exist */
 		}
 	}
-	
+
 	if( (nd->subtype == SHOP || nd->subtype == CASHSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao]
 		aFree(nd->u.shop.shop_item);
 	else if( nd->subtype == SCRIPT ) {
@@ -1809,7 +1801,7 @@ int npc_unload(struct npc_data* nd, bool single) {
 		if( single )
 			ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related
 
-		iter = mapit_geteachpc();  
+		iter = mapit_geteachpc();
 		for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) {
 			struct map_session_data *sd = ((TBL_PC*)bl);
 			if( sd && sd->npc_timer_id != INVALID_TIMER ) {
@@ -1823,13 +1815,13 @@ int npc_unload(struct npc_data* nd, bool single) {
 				delete_timer(sd->npc_timer_id, npc_timerevent);
 				sd->npc_timer_id = INVALID_TIMER;
 			}
-		}  
+		}
 		mapit_free(iter);
 
 		if (nd->u.scr.timerid != INVALID_TIMER) {
 			const struct TimerData *td = NULL;
 			td = get_timer(nd->u.scr.timerid);
-			if (td && td->data) 
+			if (td && td->data)
 				ers_free(timer_event_ers, (void*)td->data);
 			delete_timer(nd->u.scr.timerid, npc_timerevent);
 		}
@@ -1988,20 +1980,20 @@ static void npc_parsename(struct npc_data* nd, const char* name, const char* sta
 		ShowDebug("other npc in '%s' :\n   display name '%s'\n   unique name '%s'\n   map=%s, x=%d, y=%d\n",dnd->path, dnd->name, dnd->exname, other_mapname, dnd->bl.x, dnd->bl.y);
 		safestrncpy(nd->exname, newname, sizeof(nd->exname));
 	}
-	
+
 	if( npc_last_path != filepath ) {
 		struct npc_path_data * npd = NULL;
-		
+
 		if( !(npd = strdb_get(npc_path_db,filepath) ) ) {
 			CREATE(npd, struct npc_path_data, 1);
 			strdb_put(npc_path_db, filepath, npd);
-			
+
 			CREATE(npd->path, char, strlen(filepath)+1);
 			safestrncpy(npd->path, filepath, strlen(filepath)+1);
-			
+
 			npd->references = 0;
 		}
-		
+
 		nd->path = npd->path;
 		npd->references++;
 
@@ -2122,7 +2114,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const
 /// Parses a shop/cashshop npc.
 static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath)
 {
-	//TODO: could be rewritten to NOT need this temp array [ultramage] 
+	//TODO: could be rewritten to NOT need this temp array [ultramage]
 	#define MAX_SHOPITEM 100
 	struct npc_item_list items[MAX_SHOPITEM];
 	char *p;
@@ -2144,7 +2136,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const
 			ShowError("npc_parse_shop: Invalid shop definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
 			return strchr(start,'\n');// skip and continue
 		}
-		
+
 		m = map_mapname2mapid(mapname);
 	}
 
@@ -2464,17 +2456,17 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons
 	if( runOnInit ) {
 		char evname[EVENT_NAME_LENGTH];
 		struct event_data *ev;
-		
+
 		snprintf(evname, ARRAYLENGTH(evname), "%s::OnInit", nd->exname);
-		
+
 		if( ( ev = (struct event_data*)strdb_get(ev_db, evname) ) ) {
-			
+
 			//Execute OnInit
 			run_script(nd->u.scr.script,ev->pos,0,nd->bl.id);
-			
+
 		}
 	}
-	
+
 	return end;
 }
 
@@ -2630,7 +2622,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
 
 int npc_duplicate4instance(struct npc_data *snd, int m) {
 	char newname[NAME_LENGTH];
-	
+
 	if( map[m].instance_id == 0 )
 		return 1;
 
@@ -2858,9 +2850,9 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
 	// split atcmd parameters based on spaces
 	i = 0;
 	j = 0;
-	
+
 	temp = (char*)aMalloc(strlen(message) + 1);
-	
+
 	while( message[i] != '\0' ) {
 		if( message[i] == ' ' && k < 127 ) {
 			temp[j] = '\0';
@@ -3108,7 +3100,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con
 
 	if (w4 && !strcmpi(w4, "off"))
 		state = 0;	//Disable mapflag rather than enable it. [Skotlex]
-	
+
 	if (!strcmpi(w3, "nosave")) {
 		char savemap[32];
 		int savex, savey;
@@ -3556,7 +3548,7 @@ void npc_read_event_script(void)
 				ShowWarning("npc_read_event_script: too many occurences of event '%s'!\n", config[i].event_name);
 				break;
 			}
-			
+
 			if( (p=strchr(p,':')) && p && strcmpi(name,p)==0 )
 			{
 				script_event[i].event[count] = ed;
@@ -3576,14 +3568,14 @@ void npc_read_event_script(void)
 
 void npc_clear_pathlist(void) {
 	struct npc_path_data *npd = NULL;
-	DBIterator *path_list = db_iterator(npc_path_db);	
-	
+	DBIterator *path_list = db_iterator(npc_path_db);
+
 	/* free all npc_path_data filepaths */
 	for( npd = dbi_first(path_list); dbi_exists(path_list); npd = dbi_next(path_list) ) {
 		if( npd->path )
 			aFree(npd->path);
 	}
-	
+
 	dbi_destroy(path_list);
 }
 
@@ -3596,12 +3588,12 @@ int npc_reload(void) {
 	struct block_list* bl;
 
 	npc_clear_pathlist();
-	
+
 	db_clear(npc_path_db);
 
 	db_clear(npcname_db);
 	db_clear(ev_db);
-	
+
 	//Remove all npcs/mobs. [Skotlex]
 
 	iter = mapit_geteachiddb();
@@ -3662,20 +3654,20 @@ int npc_reload(void) {
 		npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
 
 	do_final_instance();
-	
+
 	for( i = 0; i < ARRAYLENGTH(instance); ++i )
 		instance_init(instance[i].instance_id);
 
 	//Re-read the NPC Script Events cache.
 	npc_read_event_script();
-	
+
 	/* refresh guild castle flags on both woe setups */
 	npc_event_doall("OnAgitInit");
 	npc_event_doall("OnAgitInit2");
-	
+
 	//Execute the OnInit event for freshly loaded npcs. [Skotlex]
 	ShowStatus("Event '"CL_WHITE"OnInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n",npc_event_doall("OnInit"));
-	
+
 	// Execute rest of the startup events if connected to char-server. [Lance]
 	if(!CheckForCharServer()){
 		ShowStatus("Event '"CL_WHITE"OnInterIfInit"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInit"));
@@ -3689,7 +3681,7 @@ bool npc_unloadfile( const char* path ) {
 	DBIterator * iter = db_iterator(npcname_db);
 	struct npc_data* nd = NULL;
 	bool found = false;
-	
+
 	for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) {
 		if( nd->path && strcasecmp(nd->path,path) == 0 ) {
 			found = true;
@@ -3697,12 +3689,12 @@ bool npc_unloadfile( const char* path ) {
 			npc_unload(nd, true);
 		}
 	}
-	
+
 	dbi_destroy(iter);
-	
+
 	if( found ) /* refresh event cache */
 		npc_read_event_script();
-	
+
 	return found;
 }
 
@@ -3712,7 +3704,7 @@ void do_clear_npc(void) {
 }
 
 /*==========================================
- * Destructor 
+ * Destructor
  *------------------------------------------*/
 int do_final_npc(void) {
 	npc_clear_pathlist();
@@ -3770,15 +3762,15 @@ int do_init_npc(void)
 	//Stock view data for normal npcs.
 	memset(&npc_viewdb, 0, sizeof(npc_viewdb));
 	npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here.
-	for( i = 1; i < MAX_NPC_CLASS; i++ ) 
+	for( i = 1; i < MAX_NPC_CLASS; i++ )
 		npc_viewdb[i].class_ = i;
 
 	ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1);
 	npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
 	npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
-	
+
 	timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
-	
+
 	// process all npc files
 	ShowStatus("Loading NPCs...\r");
 	for( file = npc_src_files; file != NULL; file = file->next ) {
@@ -3822,6 +3814,6 @@ int do_init_npc(void)
 	fake_nd->u.scr.timerid = INVALID_TIMER;
 	map_addiddb(&fake_nd->bl);
 	// End of initialization
-	
+
 	return 0;
 }

+ 25 - 25
src/map/party.c

@@ -36,7 +36,7 @@ static unsigned long party_booking_nextid = 1;
 int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data);
 
 /*==========================================
- * Fills the given party_member structure according to the sd provided. 
+ * Fills the given party_member structure according to the sd provided.
  * Used when creating/adding people to a party. [Skotlex]
  *------------------------------------------*/
 static void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader)
@@ -254,7 +254,7 @@ int party_recv_info(struct party* sp, int char_id)
 	int added_count = 0;
 	int i;
 	int member_id;
-	
+
 	nullpo_ret(sp);
 
 	p = (struct party_data*)idb_get(party_db, sp->party_id);
@@ -336,7 +336,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
 {
 	struct party_data *p;
 	int i;
-	
+
 	nullpo_ret(sd);
 
 	if( ( p = party_search(sd->status.party_id) ) == NULL )
@@ -357,7 +357,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
 		clif_party_inviteack(sd, (tsd?tsd->status.name:""), 3);
 		return 0;
 	}
-	
+
 	// confirm whether the account has the ability to invite before checking the player
 	if( !pc_has_permission(sd, PC_PERM_PARTY) || (tsd && !pc_has_permission(tsd, PC_PERM_PARTY)) ) {
 		clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player."
@@ -386,7 +386,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
 		clif_party_inviteack(sd,tsd->status.name,0);
 		return 0;
 	}
-		
+
 	tsd->party_invite=sd->status.party_id;
 	tsd->party_invite_account=sd->status.account_id;
 
@@ -588,7 +588,7 @@ int party_broken(int party_id)
 	p = party_search(party_id);
 	if( p == NULL )
 		return 0;
-		
+
 	if( p->instance_id )
 	{
 		instance[p->instance_id].party_id = 0;
@@ -650,7 +650,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
 	}
 
 	if( map[sd->bl.m].flag.partylock )
-	{               
+	{
 		clif_displaymessage(sd->fd, msg_txt(287));
 		return false;
 	}
@@ -714,7 +714,7 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m
 	m->lv = lv;
 	//Check if they still exist on this map server
 	p->data[i].sd = party_sd_check(party_id, account_id, char_id);
-	
+
 	clif_party_info(p,NULL);
 	return 0;
 }
@@ -741,7 +741,7 @@ void party_send_movemap(struct map_session_data *sd)
 
 	if (sd->fd) { // synchronize minimap positions with the rest of the party
 		for(i=0; i < MAX_PARTY; i++) {
-			if (p->data[i].sd && 
+			if (p->data[i].sd &&
 				p->data[i].sd != sd &&
 				p->data[i].sd->bl.m == sd->bl.m)
 			{
@@ -765,7 +765,7 @@ int party_send_logout(struct map_session_data *sd)
 
 	if(!sd->status.party_id)
 		return 0;
-	
+
 	intif_party_changemap(sd,0);
 	p=party_search(sd->status.party_id);
 	if(!p) return 0;
@@ -775,7 +775,7 @@ int party_send_logout(struct map_session_data *sd)
 		memset(&p->data[i], 0, sizeof(p->data[0]));
 	else
 		ShowError("party_send_logout: Failed to locate member %d:%d in party %d!\n", sd->status.account_id, sd->status.char_id, p->party.party_id);
-	
+
 	return 1;
 }
 
@@ -823,7 +823,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, int skillid, in
 		default:
 			return 0; //Unknown case?
 	}
-	
+
 	for(i=0;i<MAX_PARTY;i++){
 		if ((p_sd = p->data[i].sd) == NULL)
 			continue;
@@ -949,7 +949,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
 		pc_gainexp(sd[i], src, base_exp, job_exp, false);
 
 		if (zeny) // zeny from mobs [Valaris]
-			pc_getzeny(sd[i],zeny);
+			pc_getzeny(sd[i],zeny,LOG_TYPE_OTHER,NULL);
 	}
 	return 0;
 }
@@ -973,7 +973,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
 
 				if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) )
 					continue;
-				
+
 				if (pc_additem(psd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))
 					continue; //Chosen char can't pick up loot.
 
@@ -1008,7 +1008,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
 		}
 	}
 
-	if (!target) { 
+	if (!target) {
 		target = sd; //Give it to the char that picked it up
 		if ((i=pc_additem(sd,item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)))
 			return i;
@@ -1036,7 +1036,7 @@ int party_sub_count(struct block_list *bl, va_list ap)
 
 	if (sd->state.autotrade)
 		return 0;
-	
+
 	if (battle_config.idle_no_share && pc_isidle(sd))
 		return 0;
 
@@ -1052,9 +1052,9 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_sess
 	struct block_list *list[MAX_PARTY];
 	int blockcount=0;
 	int total = 0; //Return value.
-	
+
 	nullpo_ret(sd);
-	
+
 	if((p=party_search(sd->status.party_id))==NULL)
 		return 0;
 
@@ -1073,11 +1073,11 @@ int party_foreachsamemap(int (*func)(struct block_list*,va_list),struct map_sess
 			(psd->bl.x<x0 || psd->bl.y<y0 ||
 			 psd->bl.x>x1 || psd->bl.y>y1 ) )
 			continue;
-		list[blockcount++]=&psd->bl; 
+		list[blockcount++]=&psd->bl;
 	}
 
 	map_freeblock_lock();
-	
+
 	for(i=0;i<blockcount;i++)
 	{
 		va_list ap;
@@ -1120,7 +1120,7 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi
 		clif_PartyBookingRegisterAck(sd, 2);
 		return;
 	}
-	
+
 	memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
 	pb_ad->starttime = (int)time(NULL);
 	pb_ad->p_detail.level = level;
@@ -1141,10 +1141,10 @@ void party_booking_update(struct map_session_data *sd, short* job)
 	struct party_booking_ad_info *pb_ad;
 
 	pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id);
-	
+
 	if( pb_ad == NULL )
 		return;
-	
+
 	pb_ad->starttime = (int)time(NULL);// Update time.
 
 	for(i=0;i<PARTY_BOOKING_JOBS;i++)
@@ -1162,9 +1162,9 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
 	struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
 	bool more_result = false;
 	DBIterator* iter = db_iterator(party_booking_db);
-	
+
 	memset(result_list, 0, sizeof(result_list));
-	
+
 	for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) )
 	{
 		if (pb_ad->index < lastindex || (level && (pb_ad->p_detail.level < level-15 || pb_ad->p_detail.level > level)))

+ 16 - 10
src/map/pc.c

@@ -171,7 +171,7 @@ static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data
 		memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int));
 	sd->spirit_timer[sd->spiritball] = INVALID_TIMER;
 
-	clif_spiritball(sd);
+	clif_spiritball(&sd->bl);
 
 	return 0;
 }
@@ -206,7 +206,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
 	if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
 		clif_millenniumshield(sd,sd->spiritball);
 	else
-		clif_spiritball(sd);
+		clif_spiritball(&sd->bl);
 
 	return 0;
 }
@@ -245,7 +245,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
 		if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
 			clif_millenniumshield(sd,sd->spiritball);
 		else
-			clif_spiritball(sd);
+			clif_spiritball(&sd->bl);
 	}
 	return 0;
 }
@@ -3586,7 +3586,7 @@ int pc_inventoryblank(struct map_session_data *sd)
 /*==========================================
  * attempts to remove zeny from player (sd)
  *------------------------------------------*/
-int pc_payzeny(struct map_session_data *sd,int zeny)
+int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
 {
 	nullpo_ret(sd);
 
@@ -3602,6 +3602,8 @@ int pc_payzeny(struct map_session_data *sd,int zeny)
 	sd->status.zeny -= zeny;
 	clif_updatestatus(sd,SP_ZENY);
 
+	if(!tsd) tsd = sd;
+	log_zeny(sd, type, tsd, -zeny);
 	if( zeny > 0 && sd->state.showzeny ) {
 		char output[255];
 		sprintf(output, "Removed %dz.", zeny);
@@ -3700,8 +3702,9 @@ void pc_getcash(struct map_session_data *sd, int cash, int points)
 
 /*==========================================
  * Attempts to give zeny to player (sd)
+ * tsd (optional) from who for log (if null take sd)
  *------------------------------------------*/
-int pc_getzeny(struct map_session_data *sd,int zeny)
+int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, struct map_session_data *tsd)
 {
 	nullpo_ret(sd);
 
@@ -3717,6 +3720,8 @@ int pc_getzeny(struct map_session_data *sd,int zeny)
 	sd->status.zeny += zeny;
 	clif_updatestatus(sd,SP_ZENY);
 
+	if(!sd) tsd = sd;
+	log_zeny(sd, type, tsd, zeny);
 	if( zeny > 0 && sd->state.showzeny ) {
 		char output[255];
 		sprintf(output, "Gained %dz.", zeny);
@@ -4569,8 +4574,7 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target)
 	{
 		int amount = md->level*10 + rnd()%100;
 
-		log_zeny(sd, LOG_TYPE_STEAL, sd, amount);
-		pc_getzeny(sd, amount);
+		pc_getzeny(sd, amount, LOG_TYPE_STEAL, NULL);
 		md->state.steal_coin_flag = 1;
 		return 1;
 	}
@@ -6449,8 +6453,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 			pet_unlocktarget(sd->pd);
 	}
 
-	if( sd->status.hom_id > 0 && battle_config.homunculus_auto_vapor )
-		merc_hom_vaporize(sd, 0);
+	if (sd->status.hom_id > 0){
+	    if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
+		    merc_hom_vaporize(sd, 0);
+	}
 
 	if( sd->md )
 		merc_delete(sd->md, 3); // Your mercenary soldier has ran away.
@@ -6646,7 +6652,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 	  	{
 			base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
 			if(base_penalty)
-				pc_payzeny(sd, base_penalty);
+				pc_payzeny(sd, base_penalty, LOG_TYPE_OTHER, NULL); //@TODO that type suck
 		}
 	}
 

+ 12 - 12
src/map/pc.h

@@ -74,7 +74,7 @@ struct s_addeffectonskill {
 	unsigned char target;
 };
 
-struct s_add_drop { 
+struct s_add_drop {
 	short id, group;
 	int race, rate;
 };
@@ -165,7 +165,7 @@ struct map_session_data {
 	int packet_ver;  // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
 	struct mmo_charstatus status;
 	struct registry save_reg;
-	
+
 	struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
 	short equip_index[14];
 	unsigned int weight,max_weight;
@@ -216,7 +216,7 @@ struct map_session_data {
 	unsigned int cansendmail_tick; // [Mail System Flood Protection]
 	unsigned int ks_floodprotect_tick; // [Kill Steal Protection]
     unsigned int bloodylust_tick; // bloodylust player timer [out/in re full-heal protection]
-	
+
 	struct {
 		short nameid;
 		unsigned int tick;
@@ -226,7 +226,7 @@ struct map_session_data {
 	short disguise; // [Valaris]
 
 	struct weapon_data right_weapon, left_weapon;
-	
+
 	// here start arrays to be globally zeroed at the beginning of status_calc_pc()
 	int param_bonus[6],param_equip[6]; //Stores card/equipment bonuses.
 	int subele[ELE_MAX];
@@ -350,7 +350,7 @@ struct map_session_data {
 	struct script_regstr *regstr;
 
 	int trade_partner;
-	struct { 
+	struct {
 		struct {
 			short index, amount;
 		} item[10];
@@ -464,7 +464,7 @@ struct map_session_data {
 		unsigned short *id;/* array of combo ids */
 		unsigned char count;
 	} combos;
-	
+
 	/**
 	 * Guarantees your friend request is legit (for bugreport:4629)
 	 **/
@@ -533,7 +533,7 @@ enum ammo_type {
 
 //Equip position constants
 enum equip_pos {
-	EQP_HEAD_LOW = 0x0001, 
+	EQP_HEAD_LOW = 0x0001,
 	EQP_HEAD_MID = 0x0200, //512
 	EQP_HEAD_TOP = 0x0100, //256
 	EQP_HAND_R   = 0x0002,
@@ -559,7 +559,7 @@ enum equip_pos {
 /// Equip positions that use a visible sprite
 #if PACKETVER < 20110111
 	#define EQP_VISIBLE EQP_HELM
-#else	
+#else
 	#define EQP_VISIBLE (EQP_HELM|EQP_GARMENT|EQP_COSTUME)
 #endif
 
@@ -608,7 +608,7 @@ enum equip_index {
 #define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle_config.natural_heal_weight_rate )
 #define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 )
 #define pc_maxparameter(sd)   ( ((((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) || (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle_config.max_baby_third_parameter : battle_config.max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle_config.max_baby_parameter : battle_config.max_parameter)) )
-/** 
+/**
  * Ranger
  **/
 #define pc_iswug(sd)       ( (sd)->sc.option&OPTION_WUG )
@@ -649,7 +649,7 @@ enum equip_index {
 	#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)
 	#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2)
 	#define pc_leftside_def(sd) ((sd)->battle_status.def)
-	#define pc_rightside_def(sd) ((sd)->battle_status.def2)	
+	#define pc_rightside_def(sd) ((sd)->battle_status.def2)
 	#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef)
 	#define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) )
 #endif
@@ -695,9 +695,9 @@ int pc_memo(struct map_session_data* sd, int pos);
 int pc_checkadditem(struct map_session_data*,int,int);
 int pc_inventoryblank(struct map_session_data*);
 int pc_search_inventory(struct map_session_data *sd,int item_id);
-int pc_payzeny(struct map_session_data*,int);
+int pc_payzeny(struct map_session_data*,int, enum e_log_pick_type type, struct map_session_data*);
 int pc_additem(struct map_session_data*,struct item*,int,e_log_pick_type);
-int pc_getzeny(struct map_session_data*,int);
+int pc_getzeny(struct map_session_data*,int, enum e_log_pick_type, struct map_session_data*);
 int pc_delitem(struct map_session_data*,int,int,int,short,e_log_pick_type);
 
 // Special Shop System

Разница между файлами не показана из-за своего большого размера
+ 147 - 147
src/map/script.c


+ 183 - 39
src/map/skill.c

@@ -615,6 +615,22 @@ int skillnotok_hom(int skillid, struct homun_data *hd)
 
 	if (hd->blockskill[i] > 0)
 		return 1;
+	switch(skillid){
+	    case MH_LIGHT_OF_REGENE:
+		if(hd->homunculus.intimacy <= 750) //if not cordial
+		    return 1;
+		break;
+	    case MH_OVERED_BOOST:
+		if(hd->homunculus.hunger <= 1) //if we starving
+		    return 1;
+	    case MH_GOLDENE_FERSE: //can be used with angriff
+		if(hd->sc.data[SC_ANGRIFFS_MODUS])
+		    return 1;
+	    case MH_ANGRIFFS_MODUS:
+		if(hd->sc.data[SC_GOLDENE_FERSE])
+		    return 1;
+		break;
+	}
 
 	//Use master's criteria.
 	return skillnotok(skillid, hd->master);
@@ -796,17 +812,18 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 					sc_start(src,SC_COMBO, 15, TK_TURNKICK,
 						(2000 - 4*sstatus->agi - 2*sstatus->dex)))
 					; //Stance triggered
-				else if(sc->data[SC_READYCOUNTER])
-				{	//additional chance from SG_FRIEND [Komurka]
+                    else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka]
 					rate = 20;
 					if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) {
 						rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100;
 						status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
 					}
-					sc_start4(src,SC_COMBO, rate, TK_COUNTER, bl->id,0,0,
+					sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id,
 						(2000 - 4*sstatus->agi - 2*sstatus->dex));
 				}
 			}
+			if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) )
+				skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0);
 		}
 
 		if (sc) {
@@ -1350,18 +1367,21 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
 	case EL_TYPOON_MIS:
 		sc_start(bl,SC_SILENCE,10*skilllv,skilllv,skill_get_time(skillid,skilllv));
 		break;
-	case MH_LAVA_SLIDE:
-		sc_start4(bl,SC_BURNING,10*skilllv,skilllv,1000,src->id,0,skill_get_time(skillid,skilllv));
-		break;
-	case MH_STAHL_HORN:
-		sc_start(bl,SC_STUN,(20 + 4 * skilllv),skilllv,skill_get_time2(skillid,skilllv));
-		break;
 	case KO_JYUMONJIKIRI: // needs more info
 		sc_start(bl,SC_JYUMONJIKIRI,25,skilllv,skill_get_time(skillid,skilllv));
 		break;
 	case KO_MAKIBISHI:
 		sc_start(bl, SC_STUN, 100, skilllv, skill_get_time2(skillid,skilllv));
 		break;
+	case MH_LAVA_SLIDE:
+		if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skilllv, skilllv, 1000, src->id, 0, skill_get_time(skillid, skilllv));
+		break;
+	case MH_STAHL_HORN:
+		sc_start(bl, SC_STUN, (20 + 4 * (skilllv-1)), skilllv, skill_get_time(skillid, skilllv));
+		break;
+	case MH_NEEDLE_OF_PARALYZE:
+		sc_start(bl, SC_PARALYSIS, 40 + (5*skilllv), skilllv, skill_get_time(skillid, skilllv));
+		break;
 	}
 
 	if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai)
@@ -2787,10 +2807,11 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap)
 	g_skillid = unit->group->skill_id;
 
 	switch (skillid) {
+		case MH_STEINWAND:
 		case MG_SAFETYWALL:
 		case AL_PNEUMA:
 		case SC_MAELSTROM:
-			if(g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM)
+			if(g_skillid != MH_STEINWAND && g_skillid != MG_SAFETYWALL && g_skillid != AL_PNEUMA && g_skillid != SC_MAELSTROM)
 				return 0;
 			break;
 		case AL_WARP:
@@ -3483,7 +3504,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 	case WM_SEVERE_RAINSTORM_MELEE:
 	case WM_GREAT_ECHO:
 	case GN_SLINGITEM_RANGEMELEEATK:
-	case MH_STAHL_HORN:
 	case KO_JYUMONJIKIRI:
 	case KO_SETSUDAN:
 	case KO_KAIHOU:
@@ -3720,7 +3740,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 	case SO_VARETYR_SPEAR:
 	case GN_CART_TORNADO:
 	case GN_CARTCANNON:
-	case MH_LAVA_SLIDE:
 	case KO_HAPPOKUNAI:
 	case KO_HUUMARANKA:
 	case KO_MUCHANAGE:
@@ -4528,6 +4547,21 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		break;
 
 
+	//recursive homon skill
+	case MH_MAGMA_FLOW:
+	case MH_XENO_SLASHER:
+	case MH_HEILIGE_STANGE:
+		if(flag & 1)
+		    skill_attack(skill_get_type(skillid), src, src, bl, skillid, skilllv, tick, flag);
+		else {
+		    map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id);
+		}
+		break;
+	case MH_STAHL_HORN:
+	case MH_NEEDLE_OF_PARALYZE:
+		skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
+		break;
+
 	case 0:/* no skill - basic/normal attack */
 		if(sd) {
 			if (flag & 3){
@@ -4545,11 +4579,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		break;
 
 	default:
-		if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
-			if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
-				clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
-		} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
-			ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid);
+		ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skillid);
 		clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion,
 			0, abs(skill_get_num(skillid, skilllv)),
 			skillid, skilllv, skill_get_hit(skillid));
@@ -4660,6 +4690,18 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			break;
 		case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex]
 			return skill_castend_damage_id (src, bl, skillid, skilllv, tick, flag);
+		case MH_STEINWAND: {
+			struct block_list *s_src = battle_get_master(src);
+			short ret;
+			if(!skill_check_unit_range(src, src->x, src->y, skillid, skilllv))  //prevent reiteration
+			    ret = skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,flag); //cast on homon
+			if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skillid, skilllv))
+			    ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skillid,skilllv,tick,flag); //cast on master
+			if (hd)
+			    skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+			return ret;
+		    }
+		    break;
 		default:
 			//Skill is actually ground placed.
 			if (src == bl && skill_get_unit_id(skillid,0))
@@ -4961,7 +5003,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		break;
 	case SA_FORTUNE:
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		if(sd) pc_getzeny(sd,status_get_lv(bl)*100);
+		if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_OTHER,NULL);
 		break;
 	case SA_TAMINGMONSTER:
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
@@ -7213,12 +7255,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0);
 		}
 		break;
-	case MH_STAHL_HORN:
-		if (sd) {
-			if( skillid == MH_GOLDENE_FERSE )
-				clif_skill_fail(sd,skillid,USESKILL_FAIL_CONDITION,0);
-		}
-		break;
+
 	case HAMI_CASTLE:	//[orn]
 		if(rnd()%100 < 20*skilllv && src != bl)
 		{
@@ -7370,7 +7407,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		break;
 	case RK_IGNITIONBREAK:
 	case LG_EARTHDRIVE:
-	case MH_LAVA_SLIDE:
 			clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6);
 			i = skill_get_splash(skillid,skilllv);
 			if( skillid == LG_EARTHDRIVE ) {
@@ -8830,12 +8866,98 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), splash_target(src), src, skillid, skilllv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id);
 		}
 		break;
+
+       case MH_SILENT_BREEZE: {
+            struct status_change *ssc = status_get_sc(src);
+	    struct block_list *m_bl = battle_get_master(src);
+            const enum sc_type scs[] = {
+                    SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION
+            };
+            int heal;
+            if(tsc){
+                for (i = 0; i < ARRAYLENGTH(scs); i++) {
+                    if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
+                }
+                if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target
+                        status_change_start(bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
+	    }
+	    heal = status_get_matk_min(src)*4;
+            status_heal(bl, heal, 0, 7);
+
+	    //now inflict silence on everyone
+	    if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun
+		status_change_start(src, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
+	    if(m_bl){
+		struct status_change *msc = status_get_sc(m_bl);
+		if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master
+		    status_change_start(m_bl, SC_SILENCE, 100, skilllv, 0,0,0, skill_get_time(skillid, skilllv),1|2|8);
+	    }
+            if (hd)
+                skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+       }
+       break;
+       case MH_OVERED_BOOST:
+            if (hd){
+                struct block_list *s_bl = battle_get_master(src);
+                if(hd->homunculus.hunger>50) //reduce hunger
+                    hd->homunculus.hunger = hd->homunculus.hunger/2;
+                else
+                    hd->homunculus.hunger = min(1,hd->homunculus.hunger);
+                if(s_bl && s_bl->type==BL_PC){
+                    status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp
+                    clif_send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info
+                    sc_start(s_bl, type, 100, skilllv, skill_get_time(skillid, skilllv)); //gene bonus
+                }
+                sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv));
+		skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+            }
+            break;
+       case MH_GRANITIC_ARMOR:
+       case MH_PYROCLASTIC: {
+                struct block_list *s_bl = battle_get_master(src);
+                if(s_bl) sc_start2(s_bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv)); //start on master
+                sc_start2(bl, type, 100, skilllv, hd->homunculus.level, skill_get_time(skillid, skilllv));
+		if (hd) skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+            }
+            break;
+
+        case MH_LIGHT_OF_REGENE:
+		if(hd){
+		    hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750)
+		    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_MAGMA_FLOW:
+        case MH_PAIN_KILLER:
+           sc_start(bl, type, 100, skilllv, skill_get_time(skillid, skilllv));
+           if (hd)
+                skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+           break;
+        case MH_SUMMON_LEGION:
+            {
+                int summons[5] = {1004, 1303, 1303, 1994, 1994};
+                int qty[5] =     {3   , 3   , 4   , 4   , 5};
+                struct mob_data *md;
+                int i;
+
+                for(i=0; i<qty[skilllv - 1]; i++){ //easy way
+                    md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skilllv - 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(skillid, skilllv), 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);
+                    }
+                }
+		if (hd)
+			skill_blockhomun_start(hd, skillid, skill_get_cooldown(skillid, skilllv));
+            }
+            break;
 	default:
-		if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
-			if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
-				clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
-		} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
-			ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
+		ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skillid);
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		map_freeblock_unlock();
 		return 1;
@@ -9548,11 +9670,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 	case SO_WATER_INSIGNIA:
 	case SO_WIND_INSIGNIA:
 	case SO_EARTH_INSIGNIA:
-	case MH_POISON_MIST:
 	case KO_HUUMARANKA:
 	case KO_MUCHANAGE:
 	case KO_BAKURETSU:
 	case KO_ZENKAI:
+	case MH_LAVA_SLIDE:
+	case MH_VOLCANIC_ASH:
+	case MH_POISON_MIST:
+	case MH_STEINWAND:
+	case MH_XENO_SLASHER:
 		flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete).
 	case GS_GROUNDDRIFT: //Ammo should be deleted right away.
 		skill_unitsetting(src,skillid,skilllv,x,y,0);
@@ -10018,15 +10144,12 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk
 		for( i = 0; i < (skilllv+2); i++ ) {
 			x = src->x - 1 + rnd()%3;
 			y = src->y - 1 + rnd()%3;
-			skill_unitsetting(src,skillid,skilllv,x,y,0); 
+			skill_unitsetting(src,skillid,skilllv,x,y,0);
 		}
 		break;
+
 	default:
-		if( skillid >= HM_SKILLBASE && skillid <= HM_SKILLBASE + MAX_HOMUNSKILL ) {
-			if( src->type == BL_HOM && ((TBL_HOM*)src)->master->fd )
-				clif_colormes(((TBL_HOM*)src)->master, COLOR_RED, "This skill is not yet supported");
-		} else /* temporary until all the homun-s skills are supported otherwise console would fill up with pointless warnings */
-			ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
+		ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skillid);
 		return 1;
 	}
 
@@ -10335,6 +10458,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli
 	sc = status_get_sc(src);	// for traps, firewall and fogwall - celest
 
 	switch( skillid ) {
+	case MH_STEINWAND:
+	    val2 = 4 + skilllv; //nb of attack blocked
+	    break;
 	case MG_SAFETYWALL:
 	#ifdef RENEWAL
 		/**
@@ -10841,7 +10967,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 		break;
 	case UNT_SAFETYWALL:
 		if (!sce)
-			sc_start4(bl,type,100,sg->skill_lv,sg->group_id,sg->group_id,0,sg->limit);
+			sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit);
 		break;
 
 	case UNT_PNEUMA:
@@ -10991,6 +11117,11 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un
 			skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
 		break;
 
+	case UNT_VOLCANIC_ASH:
+		if (!sce)
+		    sc_start(bl, SC_ASH, 50, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); //50% chance
+		break;
+
 	case UNT_GD_LEADERSHIP:
 	case UNT_GD_GLORYWOUNDS:
 	case UNT_GD_SOULCOLD:
@@ -11703,6 +11834,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 			sg->limit = DIFF_TICK(tick, sg->tick);
 			sg->unit_id = UNT_USED_TRAPS;
 			break;
+
+		case UNT_LAVA_SLIDE:
+			skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
+			if(++sg->val1 > 4) //after 5 stop hit and destroy me
+				sg->limit = DIFF_TICK(tick, sg->tick);
+			break;
+		case UNT_POISON_MIST:
+			skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
+			status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8);
+			break;
 	}
 
 	if (bl->type == BL_MOB && ss != bl)
@@ -11807,6 +11948,7 @@ static int skill_unit_onleft (int skill_id, struct block_list *bl, unsigned int
 				//your own. Let's pray that scenario is pretty unlikely and noone will complain too much about it.
 				status_change_end(bl, SC_DANCING, INVALID_TIMER);
 			}
+		case MH_STEINWAND:
 		case MG_SAFETYWALL:
 		case AL_PNEUMA:
 		case SA_VOLCANO:
@@ -13139,7 +13281,7 @@ int skill_consume_requirement( struct map_session_data *sd, short skill, short l
 				req.zeny = 0; //Zeny is reduced on skill_attack.
 			if( sd->status.zeny < req.zeny )
 				req.zeny = sd->status.zeny;
-			pc_payzeny(sd,req.zeny);
+			pc_payzeny(sd,req.zeny,LOG_TYPE_OTHER,NULL); //@Need proper type
 		}
 	}
 
@@ -13489,6 +13631,8 @@ int skill_castfix_sc (struct block_list *bl, int time)
 	if (sc && sc->count) {
 		if (sc->data[SC_SLOWCAST])
 			time += time * sc->data[SC_SLOWCAST]->val2 / 100;
+        if (sc->data[SC_PARALYSIS])
+            time += sc->data[SC_PARALYSIS]->val3;
 		if (sc->data[SC_SUFFRAGIUM]) {
 			time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
 			status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);

+ 171 - 45
src/map/status.c

@@ -491,6 +491,26 @@ void initChangeTables(void) {
 	set_sc( HAMI_DEFENCE         , SC_DEFENCE         , SI_BLANK           , SCB_DEF );
 	set_sc( HAMI_BLOODLUST       , SC_BLOODLUST       , SI_BLANK           , SCB_BATK|SCB_WATK );
 
+	// Homunculus S
+	add_sc(MH_STAHL_HORN, SC_STUN);
+	set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
+	set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE,  SCB_ASPD|SCB_MAXHP);
+	add_sc( MH_STEINWAND, SC_SAFETYWALL );
+	add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER);
+	set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD);
+	add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE);
+	set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
+	set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
+	set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
+	set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
+	add_sc(MH_LAVA_SLIDE, SC_BURNING);
+	set_sc(MH_NEEDLE_OF_PARALYZE, SC_PARALYSIS, SI_NEEDLE_OF_PARALYZE, SCB_DEF2);
+	add_sc(MH_POISON_MIST, SC_BLIND);
+	set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
+
+	add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE);
+
+
 	add_sc( MER_CRASH            , SC_STUN            );
 	set_sc( MER_PROVOKE          , SC_PROVOKE         , SI_PROVOKE         , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
 	add_sc( MS_MAGNUM            , SC_WATK_ELEMENT    );
@@ -728,13 +748,6 @@ void initChangeTables(void) {
 	set_sc_with_vfx( OB_AKAITSUKI		, SC_AKAITSUKI			 , SI_AKAITSUKI			   , SCB_NONE );
 	set_sc( OB_OBOROGENSOU		, SC_GENSOU				 , SI_GENSOU			   , SCB_NONE );
 
-	add_sc( MH_STAHL_HORN		 , SC_STUN            );
-	set_sc( MH_ANGRIFFS_MODUS	 , SC_ANGRIFFS_MODUS  , SI_ANGRIFFS_MODUS	, SCB_BATK|SCB_WATK|SCB_DEF|SCB_FLEE );
-	set_sc( MH_GOLDENE_FERSE	 , SC_GOLDENE_FERSE   , SI_GOLDENE_FERSE	, SCB_SPEED|SCB_FLEE|SCB_ATK_ELE );
-	add_sc( MH_LAVA_SLIDE		 , SC_BURNING         );
-	add_sc( MH_POISON_MIST		 , SC_BLIND			  );
-	set_sc( MH_ERASER_CUTTER	 , SC_ERASER_CUTTER   , SI_BLANK			, SCB_NONE );
-
 	// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
 	SkillStatusChangeTable[SL_ALCHEMIST]   = (sc_type)MAPID_ALCHEMIST,
 	SkillStatusChangeTable[SL_MONK]        = (sc_type)MAPID_MONK,
@@ -1034,6 +1047,9 @@ void initChangeTables(void) {
 	StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST;
 	StatusChangeStateTable[SC_SILENCE]             |= SCS_NOCAST;
 
+	//Homon S
+	StatusChangeStateTable[SC_PARALYSIS]               |= SCS_NOMOVE;
+
 }
 
 static void initDummyData(void)
@@ -1294,9 +1310,17 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
 
 		return hp+sp;
 	}
-
-	if( target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*)target)->state.rebirth )
-	{// Ensure the monster has not already rebirthed before doing so.
+    if(target->type == BL_PC){
+        TBL_PC *sd = BL_CAST(BL_PC,target);
+        TBL_HOM *hd = sd->hd;
+        if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){
+            clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage
+            clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0));
+            status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
+            return hp + sp;
+        }
+    }
+    if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {// Ensure the monster has not already rebirthed before doing so.
 		status_revive(target, sc->data[SC_REBIRTH]->val2, 0);
 		status_change_clear(target,0);
 		((TBL_MOB*)target)->state.rebirth = 1;
@@ -3254,6 +3278,7 @@ static unsigned short status_calc_dmotion(struct block_list *bl, struct status_c
 #ifdef RENEWAL_ASPD
 static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag);
 #endif
+static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int);
 static unsigned int status_calc_maxhp(struct block_list *,struct status_change *,unsigned int);
 static unsigned int status_calc_maxsp(struct block_list *,struct status_change *,unsigned int);
 static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element);
@@ -3809,10 +3834,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			if(status->aspd_rate != 1000) // absolute percentage modifier
 				amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10;
 #endif
-			//fixed value added
+			//@TODO move FIGHTINGSPIRIT in fix_aspd
 			if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 )
 				amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40;
-
+			amotion = status_calc_fix_aspd(bl, sc, amotion);
 			status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
 
 			status->adelay = 2*status->amotion;
@@ -3826,6 +3851,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			if(status->aspd_rate != 1000)
 				amotion = amotion*status->aspd_rate/1000;
 
+			amotion = status_calc_fix_aspd(bl, sc, amotion);
 			status->amotion = cap_value(amotion,battle_config.max_aspd,2000);
 
 			status->adelay = status->amotion;
@@ -3838,6 +3864,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag)
 			if(status->aspd_rate != 1000)
 				amotion = amotion*status->aspd_rate/1000;
 
+			amotion = status_calc_fix_aspd(bl, sc, amotion);
 			status->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000);
 
 			temp = b_status->adelay*status->aspd_rate/1000;
@@ -4407,10 +4434,17 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
 		batk += sc->data[SC_FULL_SWING_K]->val1;
 	if(sc->data[SC_ODINS_POWER])
 		batk += 70;
-	if(sc->data[SC_ANGRIFFS_MODUS])
-		batk += batk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
 	if( sc->data[SC_ZANGETSU] )
 		batk += batk * sc->data[SC_ZANGETSU]->val2 / 100;
+	if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
+		if(status_get_element(bl) == ELE_WATER) //water type
+			batk /= 2;
+	}
+	if(sc->data[SC_PYROCLASTIC])
+		batk += sc->data[SC_PYROCLASTIC]->val2;
+	if (sc->data[SC_ANGRIFFS_MODUS])
+		batk += sc->data[SC_ANGRIFFS_MODUS]->val2;
+
 	return (unsigned short)cap_value(batk,0,USHRT_MAX);
 }
 
@@ -4597,6 +4631,8 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
 		hit -= hit * 20 / 100;
 	if(sc->data[SC_INSPIRATION])
 		hit += 5 * sc->data[SC_INSPIRATION]->val1;
+	if (sc->data[SC_ASH])
+		hit /= 2;
 
 	return (short)cap_value(hit,1,SHRT_MAX);
 }
@@ -4668,14 +4704,18 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
 		flee += flee * sc->data[SC_ZEPHYR]->val2 / 100;
 	if( sc->data[SC_MARSHOFABYSS] )
 		flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1);
-	if( sc->data[SC_ANGRIFFS_MODUS] )
-		flee -= flee * sc->data[SC_ANGRIFFS_MODUS]->val3 / 100;
-	if( sc->data[SC_GOLDENE_FERSE ] )
-		flee -= flee * sc->data[SC_GOLDENE_FERSE ]->val2 / 100;
 #ifdef RENEWAL
 	if( sc->data[SC_SPEARQUICKEN] )
 		flee += 2 * sc->data[SC_SPEARQUICKEN]->val1;
 #endif
+	if (sc->data[SC_ANGRIFFS_MODUS])
+		flee -= sc->data[SC_ANGRIFFS_MODUS]->val3;
+	if (sc->data[SC_OVERED_BOOST])
+		flee = max(flee,sc->data[SC_OVERED_BOOST]->val2);
+	if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob
+		if(status_get_element(bl) == ELE_WATER) //water type
+			flee /= 2;
+	}
 
 	return (short)cap_value(flee,1,SHRT_MAX);
 }
@@ -4765,7 +4805,11 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
 	if(sc->data[SC_ODINS_POWER])
 		def -= 20;
 	if( sc->data[SC_ANGRIFFS_MODUS] )
-		def -= def * sc->data[SC_ANGRIFFS_MODUS]->val4 / 100;
+		def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
+	if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
+		if(status_get_race(bl)==RC_PLANT)
+			def /= 2;
+	}
 
 	return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);;
 }
@@ -4823,6 +4867,12 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
 		def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
 	if( sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4)
 		def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100;
+	if(sc->data[SC_ASH] && (bl->type==BL_MOB)){
+		if(status_get_race(bl)==RC_PLANT)
+			def2 /= 2;
+	}
+	if (sc->data[SC_PARALYSIS])
+		def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100;
 
 #ifdef RENEWAL
 	return (short)cap_value(def2,SHRT_MIN,SHRT_MAX);
@@ -5212,6 +5262,28 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s
 }
 #endif
 
+static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) {
+    if (!sc || !sc->count)
+        return cap_value(aspd, 0, 2000);
+
+    if (!sc->data[SC_QUAGMIRE]) {
+        if (sc->data[SC_FIGHTINGSPIRIT])
+            aspd += sc->data[SC_FIGHTINGSPIRIT]->val3;
+        if ((sc->data[SC_GUST_OPTION]
+                || sc->data[SC_BLAST_OPTION]
+                || sc->data[SC_WILD_STORM_OPTION])
+                )
+            aspd -= 50; // ventus passive = +5 ASPD
+        if (sc->data[SC_OVERED_BOOST]){
+	    aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10;
+        }
+//	if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 )
+//	    aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4;
+    }
+
+    return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
+}
+
 /// Calculates an object's ASPD modifier (alters the base amotion value).
 /// Note that the scale of aspd_rate is 1000 = 100%.
 static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate)
@@ -5258,9 +5330,6 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
 			max < sc->data[SC_FLEET]->val2)
 			max = sc->data[SC_FLEET]->val2;
 
-		if( sc->data[SC_GOLDENE_FERSE] && max < sc->data[SC_GOLDENE_FERSE]->val3 )
-			max = sc->data[SC_GOLDENE_FERSE]->val3;
-
 		if(sc->data[SC_ASSNCROS] &&
 			max < sc->data[SC_ASSNCROS]->val2)
 		{
@@ -5346,6 +5415,10 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change *
 		aspd_rate -= sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1 * 10;
 	if( sc->data[SC_INCASPDRATE] )
 		aspd_rate -= sc->data[SC_INCASPDRATE]->val1 * 10;
+	if( sc->data[SC_PAIN_KILLER])
+		aspd_rate += sc->data[SC_PAIN_KILLER]->val2 * 10;
+	if( sc->data[SC_GOLDENE_FERSE])
+		aspd_rate -= sc->data[SC_GOLDENE_FERSE]->val3 * 10;
 
 	return (short)cap_value(aspd_rate,0,SHRT_MAX);
 }
@@ -5416,6 +5489,10 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
 		maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100;
 	if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
 		maxhp += 500;
+	if (sc->data[SC_ANGRIFFS_MODUS])
+		maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100;
+	if (sc->data[SC_GOLDENE_FERSE])
+		maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100;
 
 	return cap_value(maxhp,1,UINT_MAX);
 }
@@ -5516,8 +5593,8 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch
 		return ELE_GHOST;
 	if(sc->data[SC_TIDAL_WEAPON_OPTION] || sc->data[SC_TIDAL_WEAPON] )
 		return ELE_WATER;
-	if(sc->data[SC_GOLDENE_FERSE] && rand()%100 < sc->data[SC_GOLDENE_FERSE]->val4)
-		return ELE_HOLY;
+    if(sc->data[SC_PYROCLASTIC])
+        return ELE_FIRE;
 	return (unsigned char)cap_value(element,0,UCHAR_MAX);
 }
 
@@ -6118,6 +6195,9 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti
 	case SC_KYOUGAKU:
 		tick -= 30*status->int_;
 		break;
+        case SC_PARALYSIS:
+            tick -= 50 * (status->vit + status->luk); //(1000/20);
+            break;
 	default:
 		//Effect that cannot be reduced? Likely a buff.
 		if (!(rnd()%10000 < rate))
@@ -6306,6 +6386,12 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 	undead_flag = battle_check_undead(status->race,status->def_ele);
 	//Check for inmunities / sc fails
 	switch (type) {
+        case SC_ANGRIFFS_MODUS:
+        case SC_GOLDENE_FERSE:
+             if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS])
+                     || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE])
+                     )
+                return 0;
 	case SC_STONE:
 		if(sc->data[SC_POWER_OF_GAIA])
 			return 0;
@@ -6609,6 +6695,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			case SC_BURNING: // Place here until we have info about its behavior on Boss-monsters. [pakpil]
 			case SC_MARSHOFABYSS:
 			case SC_ADORAMUS:
+			case SC_PARALYSIS:
 
 			// Exploit prevention - kRO Fix
 			case SC_PYREXIA:
@@ -7654,16 +7741,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			val3 = 3*val1; //Leech chance
 			val4 = 20; //Leech percent
 			break;
-		case SC_ANGRIFFS_MODUS:
-			val2 = 70 + 30*val1; //atk
-			val3 = 50 + 20*val1; //flee
-			val4 = 60 + 20*val1; //def
-			break;
-		case SC_GOLDENE_FERSE:
-			val2 = 20 + 10*val1; //flee
-			val3 = 10 + 4*val1; //aspd
-			val4 = 2 + 2*val1; //chance to issue holy-ele attack
-			break;
 		case SC_FLEET:
 			val2 = 30*val1; //Aspd change
 			val3 = 5+5*val1; //bAtk/wAtk rate change
@@ -8318,7 +8395,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 			break;
 		case SC_KYOUGAKU:
 			val2 = 2*val1 + rand()%val1;
-			clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); 
+			clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0);
 			break;
 		case SC_KAGEMUSYA:
 			val3 = val1 * 2;
@@ -8351,6 +8428,41 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 					status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100);
 			}
 			break;
+			case SC_ANGRIFFS_MODUS:
+			    val2 = 50 + 20 * val1; //atk bonus
+			    val3 = 40 + 20 * val1; // Flee reduction.
+			    val4 = tick/1000; // hp/sp reduction timer
+			    tick_time = 1000;
+			    break;
+			case SC_GOLDENE_FERSE:
+			    val2 = 10 + 10*val1; //max hp bonus
+			    val3 = 6 + 4 * val1; // Aspd Bonus
+			    val4 = 2 + 2 * val1; // Chance of holy attack
+			    break;
+			case SC_OVERED_BOOST:
+			    val2 = 300 + 40*val1; //flee bonus
+			    val3 = 179 + 2*val1; //aspd bonus
+			    break;
+			case SC_GRANITIC_ARMOR:
+			    val2 = 2*val1; //dmg reduction
+			    val3 = 6*val1; //dmg on status end
+			    break;
+			case SC_MAGMA_FLOW:
+			    val2 = 3*val1; //activation chance
+			    break;
+			case SC_PYROCLASTIC:
+			    val2 += 10*val1; //atk bonus
+			    break;
+			case SC_PARALYSIS: //[Lighta] need real info
+			    val2 = 2*val1; //def reduction
+			    val3 = 500*val1; //varcast augmentation
+			    break;
+			case SC_PAIN_KILLER: //[Lighta] need real info
+			    val2 = 2*val1; //aspd reduction %
+			    val3 = 2*val1; //dmg reduction %
+			    if(sc->data[SC_PARALYSIS])
+				sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
+			    break;
 		default:
 			if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
 			{	//Status change with no calc, no icon, and no skill associated...?
@@ -8407,6 +8519,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
 		case SC_NETHERWORLD:
 		case SC_MEIKYOUSISUI:
 		case SC_KYOUGAKU:
+		case SC_PARALYSIS:
 			unit_stop_walking(bl,1);
 		break;
 		case SC_HIDING:
@@ -8877,6 +8990,17 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 	vd = status_get_viewdata(bl);
 	calc_flag = StatusChangeFlagTable[type];
 	switch(type){
+        case SC_GRANITIC_ARMOR:{
+            int dammage = status->max_hp*sce->val3/100;
+            if(status->hp < dammage) //to not kill him
+                dammage = status->hp-1;
+            status_damage(NULL, bl, dammage,0,0,1);
+            break;
+        }
+        case SC_PYROCLASTIC:
+            if(bl->type == BL_PC)
+                skill_break_equip(bl,EQP_WEAPON,10000,BCT_SELF);
+            break;
 		case SC_WEDDING:
 		case SC_XMAS:
 		case SC_SUMMER:
@@ -10274,8 +10398,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_WIND_STEP:
 	case SC_STONE_SHIELD:
 	case SC_SOLID_SKIN:
-		if( !status_charge(bl,0,sce->val2) )
-		{
+		if( !status_charge(bl,0,sce->val2) ){
 			struct block_list *s_bl = battle_get_master(bl);
 			if( s_bl )
 				status_change_end(s_bl,type+1,INVALID_TIMER);
@@ -10286,8 +10409,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		return 0;
 
 	case SC_STOMACHACHE:
-		if( --(sce->val4) > 0 )
-		{
+		if( --(sce->val4) > 0 ){
 			status_charge(bl,0,sce->val2);	// Reduce 8 every 10 seconds.
 			if( sd && !pc_issit(sd) )	// Force to sit every 10 seconds.
 			{
@@ -10308,8 +10430,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		sc_timer_next(600000 + tick, status_change_timer, bl->id, data);
 		return 0;
 	case SC_MEIKYOUSISUI:
-		if( --(sce->val4) > 0 )
-		{
+		if( --(sce->val4) > 0 ){
 			status_heal(bl, status->max_hp * (sce->val1+1) / 100, status->max_sp * sce->val1 / 100, 0);
 			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
 			return 0;
@@ -10317,12 +10438,17 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		break;
 	case SC_IZAYOI:
 	case SC_KAGEMUSYA:
-		if( --(sce->val2) > 0 )
-		{
-			if(!status_charge(bl, 0, 1))
-				break;
+		if( --(sce->val2) > 0 ){
+			if(!status_charge(bl, 0, 1)) break;
 			sc_timer_next(1000+tick, status_change_timer, bl->id, data);
 			return 0;
+		}
+				break;
+	case SC_ANGRIFFS_MODUS:
+		if(--(sce->val4) >= 0) { //drain hp/sp
+			if( !status_charge(bl,100,20) ) break;
+			sc_timer_next(1000+tick,status_change_timer,bl->id, data);
+			return 0;
 		}
 		break;
 	}

+ 15 - 4
src/map/status.h

@@ -613,10 +613,6 @@ typedef enum sc_type {
  * To increase the maximum value just add another status type before SC_MAXSPELLBOOK (ex. SC_SPELLBOOK7, SC_SPELLBOOK8 and so on)
  **/
 	SC_MAXSPELLBOOK,
-	/* homun-s */
-	SC_ANGRIFFS_MODUS,
-	SC_GOLDENE_FERSE,
-	SC_ERASER_CUTTER,
 	/* Max HP & SP */
 	SC_INCMHP,
 	SC_INCMSP,
@@ -635,6 +631,21 @@ 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,
+
 #ifdef RENEWAL	
 	SC_EXTREMITYFIST2,
 #endif

+ 20 - 29
src/map/trade.c

@@ -74,15 +74,15 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
 		clif_displaymessage(sd->fd, msg_txt(246));
 		clif_tradestart(sd, 2); // GM is not allowed to trade
 		return;
-	} 
-	
+	}
+
 	// Players can not request trade from far away, unless they are allowed to use @trade.
 	if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) &&
 	    (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) {
 		clif_tradestart(sd, 0); // too far
 		return ;
 	}
-	
+
 	target_sd->trade_partner = sd->status.account_id;
 	sd->trade_partner = target_sd->status.account_id;
 	clif_traderequest(target_sd, sd->status.name);
@@ -106,7 +106,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
 
 	if (sd->state.trading || !sd->trade_partner)
 		return; //Already trading or no partner set.
-	
+
 	if ((tsd = map_id2sd(sd->trade_partner)) == NULL) {
 		clif_tradestart(sd, 1); // character does not exist
 		sd->trade_partner=0;
@@ -177,7 +177,7 @@ int impossible_trade_check(struct map_session_data *sd)
 	int i, index;
 
 	nullpo_retr(1, sd);
-	
+
 	if(sd->deal.zeny > sd->status.zeny)
 	{
 		pc_setglobalreg(sd,"ZENY_HACKER",1);
@@ -220,7 +220,7 @@ int impossible_trade_check(struct map_session_data *sd)
 			} else
 				// message about the ban
 				strcpy(message_to_gm, msg_txt(508)); //  This player hasn't been banned (Ban option is disabled).
-			
+
 			intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm);
 			return 1;
 		}
@@ -257,7 +257,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
 			n = sd->deal.item[trade_i].index;
 			if (amount > inventory[n].amount)
 				return 0; //qty Exploit?
-			
+
 			data = itemdb_search(inventory[n].nameid);
 			i = MAX_INVENTORY;
 			if (itemdb_isstackable2(data)) { //Stackable item.
@@ -272,7 +272,7 @@ int trade_check(struct map_session_data *sd, struct map_session_data *tsd)
 						break;
 					}
 			}
-			
+
 			if (i == MAX_INVENTORY) {// look for an empty slot.
 				for(i = 0; i < MAX_INVENTORY && inventory2[i].nameid; i++);
 				if (i == MAX_INVENTORY)
@@ -439,7 +439,7 @@ void trade_tradeok(struct map_session_data *sd)
 
 	if(sd->state.deal_locked || !sd->state.trading)
 		return;
-	
+
 	if ((target_sd = map_id2sd(sd->trade_partner)) == NULL) {
 		trade_tradecancel(sd);
 		return;
@@ -470,7 +470,7 @@ void trade_tradecancel(struct map_session_data *sd)
 		clif_tradecancelled(sd);
 		return;
 	}
-	
+
 	for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual)
 		if (!sd->deal.item[trade_i].amount)
 			continue;
@@ -498,7 +498,7 @@ void trade_tradecancel(struct map_session_data *sd)
 		target_sd->deal.item[trade_i].index = 0;
 		target_sd->deal.item[trade_i].amount = 0;
 	}
-	
+
 	if (target_sd->deal.zeny) {
 		clif_updatestatus(target_sd, SP_ZENY);
 		target_sd->deal.zeny = 0;
@@ -525,9 +525,9 @@ void trade_tradecommit(struct map_session_data *sd)
 		trade_tradecancel(sd);
 		return;
 	}
-	
+
 	sd->state.deal_locked = 2;
-	
+
 	if (tsd->state.deal_locked < 2)
 		return; //Not yet time for trading.
 
@@ -547,7 +547,7 @@ void trade_tradecommit(struct map_session_data *sd)
 		trade_tradecancel(sd);
 		return;
 	}
-	
+
 	// trade is accepted and correct.
 	for( trade_i = 0; trade_i < 10; trade_i++ )
 	{
@@ -580,37 +580,28 @@ void trade_tradecommit(struct map_session_data *sd)
 
 	if( sd->deal.zeny || tsd->deal.zeny )
 	{
-		sd->status.zeny += tsd->deal.zeny - sd->deal.zeny;
-		tsd->status.zeny += sd->deal.zeny - tsd->deal.zeny;
-
-		//Logs Zeny (T)rade [Lupus]
-		if( sd->deal.zeny )
-			log_zeny(tsd, LOG_TYPE_TRADE, sd, sd->deal.zeny);
-		if( tsd->deal.zeny )
-			log_zeny(sd, LOG_TYPE_TRADE, tsd, tsd->deal.zeny);
+		pc_getzeny(sd,tsd->deal.zeny - sd->deal.zeny,LOG_TYPE_TRADE, tsd);
+		pc_getzeny(tsd,sd->deal.zeny - tsd->deal.zeny,LOG_TYPE_TRADE, sd);
 
 		sd->deal.zeny = 0;
 		tsd->deal.zeny = 0;
-
-		clif_updatestatus(sd, SP_ZENY);
-		clif_updatestatus(tsd, SP_ZENY);
 	}
-	
+
 	sd->state.deal_locked = 0;
 	sd->trade_partner = 0;
 	sd->state.trading = 0;
-	
+
 	tsd->state.deal_locked = 0;
 	tsd->trade_partner = 0;
 	tsd->state.trading = 0;
-	
+
 	clif_tradecompleted(sd, 0);
 	clif_tradecompleted(tsd, 0);
 
 	// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
 	if (save_settings&1)
   	{
-		chrif_save(sd,0); 
+		chrif_save(sd,0);
 		chrif_save(tsd,0);
 	}
 }

+ 1 - 0
src/map/unit.c

@@ -1249,6 +1249,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 	case RA_WUGDASH:
 		if (sc && sc->data[SC_WUGDASH])
 			casttime = -1;
+        break;
 	}
 	
 	// moved here to prevent Suffragium from ending if skill fails

+ 12 - 15
src/map/vending.c

@@ -59,7 +59,7 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
 	{	// GM is not allowed to trade
 		clif_displaymessage(sd->fd, msg_txt(246));
 		return;
-	} 
+	}
 
 	sd->vended_id = vsd->vender_id;  // register vending uid
 
@@ -139,11 +139,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
 			clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight
 			return;
 		}
-		
+
 		//Check to see if cart/vend info is in sync.
 		if( vending[j].amount > vsd->status.cart[idx].amount )
 			vending[j].amount = vsd->status.cart[idx].amount;
-		
+
 		// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
 		// here, we check cumulative amounts
 		if( vending[j].amount < amount )
@@ -152,7 +152,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
 			clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
 			return;
 		}
-		
+
 		vending[j].amount -= amount;
 
 		switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) {
@@ -168,13 +168,10 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
 		}
 	}
 
-	//Logs (V)ending Zeny [Lupus]
-	log_zeny(vsd, LOG_TYPE_VENDING, sd, (int)z);
-
-	pc_payzeny(sd, (int)z);
+	pc_payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd);
 	if( battle_config.vending_tax )
 		z -= z * (battle_config.vending_tax/10000.);
-	pc_getzeny(vsd, (int)z);
+	pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd);
 
 	for( i = 0; i < count; i++ )
 	{
@@ -202,7 +199,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
 	{
 		if( vsd->vending[i].amount == 0 )
 			continue;
-		
+
 		if( cursor != i ) // speedup
 		{
 			vsd->vending[cursor].index = vsd->vending[i].index;
@@ -236,18 +233,18 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
 }
 static int vending_checknearnpc_sub(struct block_list* bl, va_list args) {
     struct npc_data *nd = (struct npc_data*)bl;
-    
+
     if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) )
         return 0;
 
     return 1;
 }
 bool vending_checknearnpc(struct block_list * bl) {
-    
+
     if( battle_config.min_npc_vending_distance > 0 &&
             map_foreachinrange(vending_checknearnpc_sub,bl, battle_config.min_npc_vending_distance, BL_NPC) )
         return true;
-        
+
     return false;
 }
 /*==========================================
@@ -287,8 +284,8 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
         clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
         return;
     }
-        
-    
+
+
 	// filter out invalid items
 	i = 0;
 	for( j = 0; j < count; j++ )

Некоторые файлы не были показаны из-за большого количества измененных файлов