Browse Source

* Updated most of map-server to 1082
* Removed my own additions for skill delays using aspd
* Adapted skill_range_leniency to jA's code
* Fixed drop rates only limited to multiples of 100's
* Added missing code for castle_defense_rate
* Removed pc_undead_nofreeze
* Updated unrefineable items table
* Added 3 new script commands
* Added SC_SpeedUp0
* Merged itemdb_read for SQL and TXT
* Removed itemdb_read_cardillustnametable limited to TXT only
* Added reading itemslotcounttable.txt from the GRF to auto set number of slots per item
* Added a display message when reading itemslottable from the GRF
* Added options in battle_athena.conf to enable/disable reading the GRF

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

celest 20 năm trước cách đây
mục cha
commit
fa6ecf8890
20 tập tin đã thay đổi với 864 bổ sung340 xóa
  1. 25 0
      Changelog.txt
  2. 60 0
      conf-tmpl/battle_athena.conf
  3. 2 0
      db/Changelog.txt
  4. 1 0
      db/const.txt
  5. 14 14
      db/create_arrow_db.txt
  6. 15 1
      db/item_db.txt
  7. 163 79
      src/map/battle.c
  8. 13 1
      src/map/battle.h
  9. 42 0
      src/map/clif.c
  10. 1 0
      src/map/clif.h
  11. 10 3
      src/map/guild.c
  12. 112 76
      src/map/itemdb.c
  13. 14 2
      src/map/map.h
  14. 50 8
      src/map/mob.c
  15. 2 1
      src/map/npc.c
  16. 120 3
      src/map/pc.c
  17. 2 1
      src/map/pc.h
  18. 63 1
      src/map/script.c
  19. 145 141
      src/map/skill.c
  20. 10 9
      src/map/skill.h

+ 25 - 0
Changelog.txt

@@ -1,5 +1,30 @@
 Date	Added
 12/21
+        * Finished updating most of the map-server to 1082... i'll leave the more
+          technical ones for the other devs ^^; [celest]
+        * Added other new battle_athena options from jA 1082 ... descriptions not
+          translated yet [celest]
+        * Removed my own additions for skill delays using aspd and added jA's code [celest]
+        * Adapted skill_range_leniency to jA's code - should be more stable [celest]
+        * Fixed drop rates only limited to multiples of 100's - thanks to jathena
+          for pointing it out [celest]
+        * Added missing code for castle_defense_rate [celest]
+        * Removed pc_undead_nofreeze - no code for it [celest]
+        * Updated unrefineable items table - thanks to jathena [celest]
+        * Added 3 new script commands: [celest]
+          - skilleffect : shows a skill effect on the player
+          - doskill/skilluseid (originally by Qamera) : casts a skill on the player
+          - skillusepos : casts a skill on a position
+        * Added SC_SpeedUp0 [celest]
+        * Merged itemdb_read for SQL and TXT [celest]
+        * Moved itemdb_read_itemslottable in itemdb.c for better readability [celest]
+        * Removed itemdb_read_cardillustnametable limited to TXT only [celest]
+        * Added reading itemslotcounttable.txt from the GRF to auto set number of slots 
+          per item [celest]
+        * Added a display message when reading itemslottable from the GRF [celest]
+        * Added options in battle_athena.conf to enable/disable reading the GRF for
+          indoorrswtable.txt, leveluseskillspamount.txt, num2cardillustnametable.txt, 
+          itemslottable.txt & itemslotcounttable.txt [celest]
 	* Removed conf/npcs_list.txt, and placed it in npc/npcs_athena.conf
 
 12/20

+ 60 - 0
conf-tmpl/battle_athena.conf

@@ -349,8 +349,27 @@ natural_heal_skill_interval: 10000
 // The maximum weight for a character to carry when the character stops healing naturally. (in %)
 natural_heal_weight_rate: 50
 
+// You can turn the following 5 settings off if you don't need them,
+// or if you're experiencing problems with GRF loading
+//
 // Override item names from GRF file? (Note 1)
 item_name_override_grffile: yes
+//
+// Override item equip positions from GRF file? (Note 1)
+item_equip_override_grffile: yes
+//
+// Override item slots from GRF file? (Note 1)
+item_slots_override_grffile: yes
+//
+// Override 'indoors' mapflags from GRF file? (Note 1)
+indoors_override_grffile: yes
+//
+// Override SP used per level from GRF file? (Note 1)
+// Turn this off if you have a customised skill_require_db.txt
+skill_sp_override_grffile: yes
+//
+// Read card illustrations from GRF file? (Note 1)
+cardillust_read_grffile: yes
 
 // Are arrows are consumed when used on a bow? (Note 1)
 arrow_decrement: yes
@@ -470,6 +489,9 @@ player_cloak_check_type: yes
 // When a monster is cloaking, Whether the wall is checked or not. (Note 1)
 monster_cloak_check_type: no
 
+// Damage adjustments for WOE battles against defending Guild monsters (Note 2)
+castle_defense_rate: 100
+
 // Melee damage adjustments for WoE battles (Guild Vs Guild) (Note 2)
 gvg_short_attack_damage_rate: 100
 
@@ -755,5 +777,43 @@ skill_range_leniency: 1
 // Set this to 1 if your clients have langtype problems and can't display motd properly
 motd_type: 0
 
+// キャラのHP?率を設定。(100で正規の値)
+hp_rate: 100
+
+// キャラのSP?率を設定。(100で正規の値)
+sp_rate: 100
+
+//GMの行動制限  アイテ?ドロップ・倉庫出し入れ・ItemZeny交換
+gm_can_drop_lv: 0
+
+//全キャラがGMにHPメ???を常に送信するか
+disp_hpmeter: no
+
+//PC?亡時に、ドクロをドロップするか
+//0:しない 1:PvP?ップのみ 2:いつでも
+bone_drop: 0
+
+//敵のアイテ?ドロップ率をレ?トごとに個別?率をかけるかどうか
+//details = 0:個別設定なし(デフォルト) 1:それぞれ?率指定(百分率) ?detailsが0以外の場合、以前のドロップ?率は無視されます
+//          2:それぞれ?率指定(百分率)、ドロップ率上限と下限を設定?ドロップ設定0は無視します
+//例 details = 3 rate_1 = 1000 min = 20 ドロップ率1/10000?9/10000の物を10?に指定 10?しても20/10000未満の物は 20/10000に固定
+item_rate_details: 0
+//ドロップ設定1?9
+item_rate_1: 100
+item_rate_1_min: 1
+item_rate_1_max: 9
+//ドロップ設定10?99
+item_rate_10: 100
+item_rate_10_min: 10
+item_rate_10_max: 99
+//ドロップ設定100?999
+item_rate_100: 100
+item_rate_100_min: 100
+item_rate_100_max: 999
+//ドロップ設定1000?10000
+item_rate_1000: 100
+item_rate_1000_min: 1000
+item_rate_1000_max: 10000
+
 import: conf/import/battle_conf.txt
 

+ 2 - 0
db/Changelog.txt

@@ -5,6 +5,8 @@
 	Ayathoya items == Added but no effect ( all are "ect" itens)
 	Skill databases == celest working on them i believe.
 
+12/21
+        * Added the new Quivers, updated Horse Crest [celest]
 12/20
         * removed extra {},,,,,,, from each tailing [Lupus]
         * Corrected job requirements for some garments [celest]

+ 1 - 0
db/const.txt

@@ -253,6 +253,7 @@ SC_SpeedPot0	37
 SC_SpeedPot1	38
 SC_SpeedPot2	39
 SC_SpeedPot3	40
+SC_SpeedUp0	41
 SC_ATKPot	185
 SC_MATKPot	186
 SC_EncPoison	6

+ 14 - 14
db/create_arrow_db.txt

@@ -5,9 +5,9 @@
 609,1761,40
 713,1770,2
 714,1757,600,1769,600,1765,600
-715,1756,10,1768,1
+715,1756,100,1768,1
 716,1762,10,1763,1,1761,1
-717,1754,10,1759,1
+717,1754,100,1759,1
 724,1761,50,1768,10
 733,1764,50
 756,1765,50
@@ -34,14 +34,14 @@
 969,1760,50,1765,50
 984,1765,250
 985,1753,1000,1758,50
-990,1752,200
-991,1754,50
-992,1755,50
-993,1756,50
-994,1752,600,1769,5
-995,1754,150,1759,5
-996,1755,150,1768,5
-997,1756,150,1760,5
+990,1752,2000
+991,1754,500
+992,1755,500
+993,1756,500
+994,1752,6000,1769,5
+995,1754,1500,1759,5
+996,1755,1500,1768,5
+997,1756,1500,1760,5
 998,1770,100
 999,1753,100
 1000,1760,30
@@ -78,8 +78,8 @@
 2332,1751,700
 2333,1751,1000,1757,10
 2408,1770,700,1753,50
-2618,1755,50,1753,100,1764,10
-5014,1754,200,1753,200
+2618,1755,500,1753,100,1764,10
+5014,1754,2000,1753,200
 7002,1753,30,1762,5
 7008,1758,2
 7010,1753,250,1763,1
@@ -93,7 +93,7 @@
 7025,1758,800,1769,400,1768,800
 7026,1765,50
 7027,1767,100
-7035,1752,1000
-7036,1754,100
+7035,1752,10000
+7036,1754,1000
 7053,1751,40
 

+ 15 - 1
db/item_db.txt

@@ -134,7 +134,7 @@
 661,Sky_Apron,Soft Apron,2,20,0,50,,,,,10477567,2,,,,,{ pet 1275; },{}
 
 // Newer Items
-662,Horse_Crest,Crest of the Horse,2,0,0,30,0,0,0,0,10477567,2,0,0,0,0,{ itemskill 29,5,"Increase Agility Level 5"; },{}
+662,Horse_Crest,Crest of the Horse,2,0,0,30,0,0,0,0,10477567,2,0,0,0,0,{ skilleffect 29,5; sc_start SC_SpeedUp0,240000,0; },{}
 664,Gift_Box_,Gift Box,2,20,0,200,,,,,10477567,2,,,,,{ getitem -4,1; },{},
 665,Gift_Box__,Gift Box,2,20,0,200,,,,,10477567,2,,,,,{ getitem -4,1; },{},
 666,Gift_Box___,Gift Box,2,20,0,200,,,,,10477567,2,,,,,{ getitem -4,1; },{},
@@ -1721,3 +1721,17 @@
 12001,Heal_3,Heal Level 3,2,0,0,10,0,0,0,0,10477567,2,0,0,0,0,{ itemskill 28,3,"Heal Level 3"; },{}
 12002,Heal_5,Heal Level 5,2,0,0,10,0,0,0,0,10477567,2,0,0,0,0,{ itemskill 28,5,"Heal Level 5"; },{}
 12003,Teleport_1,Teleport Level 1,2,0,0,10,0,0,0,0,10477567,2,0,0,0,0,{ itemskill 26,1,"Teleport Level 1"; },{}
+
+// Arrow Quivers
+12004,Arrow_Quiver,Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1750,500; },{}
+12005,Iron_Arrow_Quiver,Iron Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1770,500; },{}
+12006,Steel_Arrow_Quiver,Steel Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1753,500; },{}
+12007,Oridecon_Arrow_Quiver,Oridecon Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1765,500; },{}
+12008,Fire_Arrow_Quiver,Fire Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1752,500; },{}
+12009,Silver_Arrow_Quiver,Silver Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1751,500; },{}
+12010,Arrow_of_Wind_Quiver,Arrow of Wind Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1755,500; },{}
+12011,Stone_Arrow_Quiver,Stone Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1756,500; },{}
+12012,Crystal_Arrow_Quiver,Crystal Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1754,500; },{}
+12013,Shadow_Arrow_Quiver,Shadow Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1767,500; },{}
+12014,Immaterial_Arrow_Quiver,Immaterial Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1757,500; },{}
+12015,Rusty_Arrow_Quiver,Rusty Arrow Quiver,2,,,250,,,,,10477567,2,,,,,{ getitem 1762,500; },{} 

+ 163 - 79
src/map/battle.c

@@ -544,9 +544,10 @@ int battle_get_baseatk(struct block_list *bl)
 
 	nullpo_retr(1, bl);
 	sc_data=battle_get_sc_data(bl);
-	if(bl->type==BL_PC && (struct map_session_data *)bl)
+	if(bl->type==BL_PC && (struct map_session_data *)bl) {
 		batk = ((struct map_session_data *)bl)->base_atk; //設定されているbase_atk
-	else { //それ以外なら
+		batk += ((struct map_session_data *)bl)->weapon_atk[((struct map_session_data *)bl)->status.weapon];
+	} else { //それ以外なら
 		int str,dstr;
 		str = battle_get_str(bl); //STR
 		dstr = str/10;
@@ -935,6 +936,8 @@ int battle_get_speed(struct block_list *bl)
 				speed -= (speed*(sc_data[SC_WINDWALK].val1*2))/100;
 			if(sc_data[SC_SLOWDOWN].timer!=-1)
 				speed = speed*150/100;
+			if(sc_data[SC_SPEEDUP0].timer!=-1)
+				speed -= speed*25/100;
 		}
 		if(speed < 1) speed = 1;
 		return speed;
@@ -1647,12 +1650,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			else if(g && guild_checkskill(g,GD_APPROVAL) <= 0)
 				damage=0;//正規ギルド承認がないとダメージ無し
 			else if (battle_config.guild_max_castles != 0 && guild_checkcastles(g)>=battle_config.guild_max_castles)
-                                damage = 0; // [MouseJstr]
+				damage = 0; // [MouseJstr]
 		}
 		else damage = 0;
 	}
 
 	if(map[bl->m].flag.gvg && damage > 0) { //GvG
+		if(bl->type == BL_MOB){	//defenseがあればダメージが減るらしい?
+			struct guild_castle *gc=guild_mapname2gc(map[bl->m].name);
+			if (gc) damage -= damage*(gc->defense/100)*(battle_config.castle_defense_rate/100);
+		}
 		if(flag&BF_WEAPON) {
 			if(flag&BF_SHORT)
 				damage=damage*battle_config.gvg_short_damage_rate/100;
@@ -1681,6 +1688,33 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 	return damage;
 }
 
+/*==========================================
+ * HP/SP吸収の計算
+ *------------------------------------------
+ */
+int battle_calc_drain(int damage, int rate, int per, int val)
+{
+	int diff = 0;
+
+	if (damage <= 0 || rate <= 0)
+		return 0;
+
+	if (per && rand()%100 < rate) {
+		diff = (damage * per) / 100;
+		if (diff == 0) {
+			if (per > 0)
+				diff = 1;
+			else
+				diff = -1;
+		}
+	}
+
+	if (val && rand()%100 < rate) {
+		diff += val;
+	}
+	return diff;
+}
+
 /*==========================================
  * 修練ダメージ
  *------------------------------------------
@@ -1925,7 +1959,7 @@ static struct Damage battle_calc_pet_weapon_attack(
 				hitrate = (hitrate*(100+5*skill_lv))/100;
 				break;
 			case SM_MAGNUM:		// マグナムブレイク
-				damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
+				damage = damage*(5*skill_lv + (wflag?65:115))/100;
 				break;
 			case MC_MAMMONITE:	// メマーナイト
 				damage = damage*(100+ 50*skill_lv)/100;
@@ -2045,6 +2079,7 @@ static struct Damage battle_calc_pet_weapon_attack(
 				hitrate= 1000000;
 				break;
 			case AM_DEMONSTRATION:	// デモンストレーション
+				hitrate= 1000000;
 				damage = damage*(100+ 20*skill_lv)/100;
 				damage2 = damage2*(100+ 20*skill_lv)/100;
 				break;
@@ -2127,7 +2162,7 @@ static struct Damage battle_calc_pet_weapon_attack(
 		if( skill_num!=NPC_CRITICALSLASH ){
 			// 対 象の防御力によるダメージの減少
 			// ディバインプロテクション(ここでいいのかな?)
-			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000 ) {	//DEF, VIT無視
+			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000 ) {	//DEF, VIT無視
 				int t_def;
 				target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
 				if(battle_config.vit_penalty_type > 0) {
@@ -2392,9 +2427,9 @@ static struct Damage battle_calc_mob_weapon_attack(
 		// ソニックブロー
 		if(sc_data){ //状態異常中のダメージ追加
 			if(sc_data[SC_OVERTHRUST].timer!=-1)	// オーバートラスト
-			damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100;
+				damage += damage*(5*sc_data[SC_OVERTHRUST].val1)/100;
 			if(sc_data[SC_TRUESIGHT].timer!=-1)	// トゥルーサイト
-			damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100;
+				damage += damage*(2*sc_data[SC_TRUESIGHT].val1)/100;
 			if(sc_data[SC_BERSERK].timer!=-1)	// バーサーク
 				damage += damage*2;
 			if(sc_data && sc_data[SC_AURABLADE].timer!=-1)	//[DracoRPG]
@@ -2413,7 +2448,7 @@ static struct Damage battle_calc_mob_weapon_attack(
 				hitrate = (hitrate*(100+5*skill_lv))/100;
 				break;
 			case SM_MAGNUM:		// マグナムブレイク
-				damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
+				damage = damage*(5*skill_lv +(wflag?65:115))/100;
 				break;
 			case MC_MAMMONITE:	// メマーナイト
 				damage = damage*(100+ 50*skill_lv)/100;
@@ -2540,6 +2575,7 @@ static struct Damage battle_calc_mob_weapon_attack(
 				hitrate= 1000000;
 				break;
 			case AM_DEMONSTRATION:	// デモンストレーション
+				hitrate = 1000000;
 				damage = damage*(100+ 20*skill_lv)/100;
 				damage2 = damage2*(100+ 20*skill_lv)/100;
 				break;
@@ -2622,7 +2658,7 @@ static struct Damage battle_calc_mob_weapon_attack(
 		if( skill_num!=NPC_CRITICALSLASH ){
 			// 対 象の防御力によるダメージの減少
 			// ディバインプロテクション(ここでいいのかな?)
-			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) {	//DEF, VIT無視
+			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != KN_AUTOCOUNTER && def1 < 1000000) {	//DEF, VIT無視
 				int t_def;
 				target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
 				if(battle_config.vit_penalty_type > 0) {
@@ -2988,9 +3024,9 @@ static struct Damage battle_calc_pc_weapon_attack(
 	{
 		damage += atkmax;
 		damage2 += atkmax_;
-		if(sd->atk_rate != 100) {
-			damage = (damage * sd->atk_rate)/100;
-			damage2 = (damage2 * sd->atk_rate)/100;
+		if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) {
+			damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+			damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
 		}
 		if(sd->state.arrow_atk)
 			damage += sd->arrow_atk;
@@ -3038,9 +3074,9 @@ static struct Damage battle_calc_pc_weapon_attack(
 			damage2 += atkmin_ + rand() % (atkmax_-atkmin_ + 1);
 		else
 			damage2 += atkmin_ ;
-		if(sd->atk_rate != 100) {
-			damage = (damage * sd->atk_rate)/100;
-			damage2 = (damage2 * sd->atk_rate)/100;
+		if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) {
+			damage = (damage * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
+			damage2 = (damage2 * (sd->atk_rate + sd->weapon_atk_rate[sd->status.weapon]))/100;
 		}
 
 		if(sd->state.arrow_atk) {
@@ -3119,8 +3155,8 @@ static struct Damage battle_calc_pc_weapon_attack(
 				hitrate = (hitrate*(100+5*skill_lv))/100;
 				break;
 			case SM_MAGNUM:		// マグナムブレイク
-				damage = damage*(5*skill_lv +(wflag)?65:115 )/100;
-				damage2 = damage2*(5*skill_lv +(wflag)?65:115 )/100;
+				damage = damage*(5*skill_lv +(wflag?65:115) )/100;
+				damage2 = damage2*(5*skill_lv +(wflag?65:115) )/100;
 				break;
 			case MC_MAMMONITE:	// メマーナイト
 				damage = damage*(100+ 50*skill_lv)/100;
@@ -3327,11 +3363,15 @@ static struct Damage battle_calc_pc_weapon_attack(
 			case AM_DEMONSTRATION:	// デモンストレーション
 				damage = damage*(100+ 20*skill_lv)/100;
 				damage2 = damage2*(100+ 20*skill_lv)/100;
+				no_cardfix = 1;
 				break;
 			case AM_ACIDTERROR:	// アシッドテラー
 				hitrate = 1000000;
 				damage = damage*(100+ 40*skill_lv)/100;
 				damage2 = damage2*(100+ 40*skill_lv)/100;
+				s_ele = 0;
+				s_ele_ = 0;
+				no_cardfix = 1;
 				break;
 			case MO_FINGEROFFENSIVE:	//指弾
 				if(battle_config.finger_offensive_type == 0) {
@@ -3374,11 +3414,6 @@ static struct Damage battle_calc_pc_weapon_attack(
 				damage2 = damage2*(240+ 60*skill_lv)/100;
 				break;
 			case BA_MUSICALSTRIKE:	// ミュージカルストライク
-				if(!sd->state.arrow_atk && sd->arrow_atk > 0) {
-					int arr = rand()%(sd->arrow_atk+1);
-					damage += arr;
-					damage2 += arr;
-				}
 				damage = damage*(60+ 40 * skill_lv)/100;
 				damage2 = damage2*(60+ 40 * skill_lv)/100;
 				if(sd->arrow_ele > 0) {
@@ -3386,7 +3421,6 @@ static struct Damage battle_calc_pc_weapon_attack(
 					s_ele_ = sd->arrow_ele;
 				}
 				flag=(flag&~BF_RANGEMASK)|BF_LONG;
-				sd->state.arrow_atk = 1;
 				break;
 			case DC_THROWARROW:	// 矢撃ち
 				if(!sd->state.arrow_atk && sd->arrow_atk > 0) {
@@ -3443,11 +3477,6 @@ static struct Damage battle_calc_pc_weapon_attack(
 				damage2 += damage2*(30*skill_lv)/100;
 				break;
 			case CG_ARROWVULCAN:			/* アローバルカン */
-				if(!sd->state.arrow_atk && sd->arrow_atk > 0) {
-					int arr = rand()%(sd->arrow_atk+1);
-					damage += arr;
-					damage2 += arr;
-				}
 				damage = damage*(200+100*skill_lv)/100;
 				damage2 = damage2*(200+100*skill_lv)/100;
 				div_=9;
@@ -3456,7 +3485,6 @@ static struct Damage battle_calc_pc_weapon_attack(
 					s_ele_ = sd->arrow_ele;
 				}
 				flag=(flag&~BF_RANGEMASK)|BF_LONG;
-				sd->state.arrow_atk = 1;
 				break;
 			case AS_SPLASHER:		/* ベナムスプラッシャー */
 				damage = damage*(200+20*skill_lv+20*pc_checkskill(sd,AS_POISONREACT))/100;
@@ -3520,7 +3548,7 @@ static struct Damage battle_calc_pc_weapon_attack(
 		if( skill_num!=NPC_CRITICALSLASH ){
 			// 対 象の防御力によるダメージの減少
 			// ディバインプロテクション(ここでいいのかな?)
-			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && def1 < 1000000) {	//DEF, VIT無視
+			if ( skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST && skill_num != KN_AUTOCOUNTER && skill_num != AM_ACIDTERROR && def1 < 1000000) {	//DEF, VIT無視
 				int t_def;
 				target_count = 1 + battle_counttargeted(target,src,battle_config.vit_penalty_count_lv);
 				if(battle_config.vit_penalty_type > 0) {
@@ -3582,11 +3610,23 @@ static struct Damage battle_calc_pc_weapon_attack(
 	// 状態異常中のダメージ追加でクリティカルにも有効なスキル
 	if (sc_data) {
 		// エンチャントデッドリーポイズン
-		if(sc_data[SC_EDP].timer != -1 && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT) {
+		if(!no_cardfix && sc_data[SC_EDP].timer != -1 && skill_num != ASC_BREAKER && skill_num != ASC_METEORASSAULT) {
 			damage += damage * (150 + sc_data[SC_EDP].val1 * 50) / 100;
-			damage2 += damage2 * (150 + sc_data[SC_EDP].val1 * 50) / 100;
 			no_cardfix = 1;
 		}
+		if (!skill_num && !(t_mode&0x20) && sc_data[SC_SACRIFICE].timer != -1) {
+			int mhp = battle_get_max_hp(src);
+			int dmg = mhp * (5 + sc_data[SC_SACRIFICE].val1 * 5) / 1000;
+			pc_heal(sd, -dmg, 0);
+			damage = dmg * (90 + sc_data[SC_SACRIFICE].val1 * 15) / 100;
+			damage2 = 0;
+			hitrate = 1000000;
+			s_ele = 0;
+			s_ele_ = 0;
+			sc_data[SC_SACRIFICE].val2 --;
+			if (sc_data[SC_SACRIFICE].val2 == 0)
+				skill_status_change_end(src, SC_SACRIFICE,-1);
+		}
 	}
 
 	// 精錬ダメージの追加
@@ -4178,7 +4218,7 @@ struct Damage battle_calc_magic_attack(
 			break;
 		case WZ_STORMGUST:	// ストームガスト
 			MATK_FIX( skill_lv*40+100 ,100 );
-			blewcount|=0x10000;
+//			blewcount|=0x10000;
 			break;
 		case AL_HOLYLIGHT:	// ホーリーライト
 			MATK_FIX( 125,100 );
@@ -4387,6 +4427,8 @@ struct Damage  battle_calc_misc_attack(
 		damage=(dex/10+int_/2+skill*3+40)*2;
 		if(flag > 1)
 			damage /= flag;
+		if(battle_get_mode(target) & 0x40)
+			damage = 1;
 		break;
 
 	case TF_THROWSTONE:	// 石投げ
@@ -4424,12 +4466,17 @@ struct Damage  battle_calc_misc_attack(
 		break;
 	case SN_FALCONASSAULT:			/* ファルコンアサルト */
 #ifdef TWILIGHT
- 		skill = pc_checkskill(sd,HT_BLITZBEAT);
-                damage=(100+50*skill_lv+(dex/10+int_/2+skill*3+40)*2) * 2;
+		if( sd==NULL || (skill = pc_checkskill(sd,HT_BLITZBEAT)) <= 0)
+			skill=0;
 #else
-		skill = pc_checkskill(sd,HT_STEELCROW); // Celest 
-		damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100;
+		if( sd==NULL || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
+			skill=0;
+		damage=((150+50*skill_lv)*(dex/10+int_/2+skill*3+40)*2)/100; // [Celest]
 #endif
+		if(flag > 1)
+			damage /= flag;
+		if(battle_get_mode(target) & 0x40)
+			damage = 1;
 		break;
 	}
 
@@ -4706,29 +4753,25 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 					if(!f) pc_heal(sd,0,-sp);
 				}
 			}
-			if(wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) {
+			if (wd.flag&BF_WEAPON && src != target && (wd.damage > 0 || wd.damage2 > 0)) {
 				int hp = 0,sp = 0;
-				if(sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->hp_drain_rate) {
-					hp += (wd.damage * sd->hp_drain_per)/100;
-					if(sd->hp_drain_rate > 0 && hp < 1) hp = 1;
-					else if(sd->hp_drain_rate < 0 && hp > -1) hp = -1;
-				}
-				if(sd->hp_drain_rate_ && sd->hp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->hp_drain_rate_) {
-					hp += (wd.damage2 * sd->hp_drain_per_)/100;
-					if(sd->hp_drain_rate_ > 0 && hp < 1) hp = 1;
-					else if(sd->hp_drain_rate_ < 0 && hp > -1) hp = -1;
-				}
-				if(sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0 && rand()%100 < sd->sp_drain_rate) {
-					sp += (wd.damage * sd->sp_drain_per)/100;
-					if(sd->sp_drain_rate > 0 && sp < 1) sp = 1;
-					else if(sd->sp_drain_rate < 0 && sp > -1) sp = -1;
+				if (!battle_config.left_cardfix_to_right) { // 二刀流左手カードの吸収系効果を右手に追加しない場合
+					hp += battle_calc_drain(wd.damage, sd->hp_drain_rate, sd->hp_drain_per, sd->hp_drain_value);
+					hp += battle_calc_drain(wd.damage2, sd->hp_drain_rate_, sd->hp_drain_per_, sd->hp_drain_value_);
+					sp += battle_calc_drain(wd.damage, sd->sp_drain_rate, sd->sp_drain_per, sd->sp_drain_value);
+					sp += battle_calc_drain(wd.damage2, sd->sp_drain_rate_, sd->sp_drain_per_, sd->sp_drain_value_);
+				} else { // 二刀流左手カードの吸収系効果を右手に追加する場合
+					int hp_drain_rate = sd->hp_drain_rate + sd->hp_drain_rate_;
+					int hp_drain_per = sd->hp_drain_per + sd->hp_drain_per_;
+					int hp_drain_value = sd->hp_drain_value + sd->hp_drain_value_;
+					int sp_drain_rate = sd->sp_drain_rate + sd->sp_drain_rate_;
+					int sp_drain_per = sd->sp_drain_per + sd->sp_drain_per_;
+					int sp_drain_value = sd->sp_drain_value + sd->sp_drain_value_;
+					hp += battle_calc_drain(wd.damage, hp_drain_rate, hp_drain_per, hp_drain_value);
+					sp += battle_calc_drain(wd.damage, sp_drain_rate, sp_drain_per, sp_drain_value);
 				}
-				if(sd->sp_drain_rate_ && sd->sp_drain_per_ > 0 && wd.damage2 > 0 && rand()%100 < sd->sp_drain_rate_) {
-					sp += (wd.damage2 * sd->sp_drain_per_)/100;
-					if(sd->sp_drain_rate_ > 0 && sp < 1) sp = 1;
-					else if(sd->sp_drain_rate_ < 0 && sp > -1) sp = -1;
-				}
-				if(hp || sp) pc_heal(sd,hp,sp);
+
+				if (hp || sp) pc_heal(sd, hp, sp);
 			}
 		}
 
@@ -4753,13 +4796,12 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
  				skill_status_change_end(target,SC_POISONREACT,-1);            
 			}         
 		}
-		if(t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1){
-			if (!(src->type == BL_MOB && mob_db[((struct mob_data *)src)->class].mode&0x20)) {
-				int lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
-				skill_status_change_end(target,SC_BLADESTOP_WAIT,-1);
-				skill_status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0);
-				skill_status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0);
-			}
+	if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1 &&
+			!(battle_get_mode(src)&0x20)) { // ボスには無効
+			int lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
+			skill_status_change_end(target,SC_BLADESTOP_WAIT,-1);
+			skill_status_change_start(src,SC_BLADESTOP,lv,1,(int)src,(int)target,skill_get_time2(MO_BLADESTOP,lv),0);
+			skill_status_change_start(target,SC_BLADESTOP,lv,2,(int)target,(int)src,skill_get_time2(MO_BLADESTOP,lv),0);
 		}
 		if(t_sc_data && t_sc_data[SC_SPLASHER].timer!=-1)	//殴ったので対象のベナムスプラッシャー状態を解除
 			skill_status_change_end(target,SC_SPLASHER,-1);
@@ -4989,17 +5031,8 @@ int battle_check_range(struct block_list *src,struct block_list *bl,int range)
 	if(src->m != bl->m)	// 違うマップ
 		return 0;
 
-	if( range>0 && range < arange )	{// 遠すぎる
-// be lenient if the skill was cast before we have moved to the correct position [Celest]
-		/* Celest: Hmm, bl isn't necessarily BL_PC... i think i'll test this more first >.< */
-		/*if (src->type == BL_PC && bl->type == BL_PC) {
-			struct map_session_data *sd;
-			nullpo_retr(0, (sd=(struct map_session_data *)bl));
-			if (sd->walktimer != -1 && !((arange-=battle_config.skill_range_leniency)<=range))
-				return 0;
-		}
-		else*/ return 0;
-	}
+	if( range>0 && range < arange )	// 遠すぎる
+		return 0;
 
 	if( arange<2 )	// 同じマスか隣接
 		return 1;
@@ -5128,6 +5161,11 @@ static const struct {
 	{ "natural_heal_skill_interval",       &battle_config.natural_heal_skill_interval},
 	{ "natural_heal_weight_rate",          &battle_config.natural_heal_weight_rate	},
 	{ "item_name_override_grffile",        &battle_config.item_name_override_grffile},
+	{ "item_equip_override_grffile",       &battle_config.item_equip_override_grffile},	// [Celest]
+	{ "item_slots_override_grffile",       &battle_config.item_slots_override_grffile},	// [Celest]
+	{ "indoors_override_grffile",          &battle_config.indoors_override_grffile},	// [Celest]
+	{ "skill_sp_override_grffile",         &battle_config.skill_sp_override_grffile},	// [Celest]
+	{ "cardillust_read_grffile",           &battle_config.cardillust_read_grffile},	// [Celest]	
 	{ "arrow_decrement",                   &battle_config.arrow_decrement			},
 	{ "max_aspd",                          &battle_config.max_aspd					},
 	{ "max_hp",                            &battle_config.max_hp					},
@@ -5202,8 +5240,26 @@ static const struct {
 	{ "invite_request_check",              &battle_config.invite_request_check		},
 	{ "skill_removetrap_type",             &battle_config.skill_removetrap_type	},
 	{ "disp_experience",                   &battle_config.disp_experience			},
-	{ "castle_defense_rate",		&battle_config.castle_defense_rate		},
-	{ "riding_weight",		&battle_config.riding_weight		},
+	{ "castle_defense_rate",               &battle_config.castle_defense_rate		},
+	{ "riding_weight",                     &battle_config.riding_weight		},
+	{ "hp_rate",					       &battle_config.hp_rate					},
+	{ "sp_rate",					       &battle_config.sp_rate					},
+	{ "gm_can_drop_lv",				       &battle_config.gm_can_drop_lv			},
+	{ "disp_hpmeter",				       &battle_config.disp_hpmeter				},
+	{ "bone_drop",				           &battle_config.bone_drop				},
+	{ "item_rate_details",				   &battle_config.item_rate_details			},
+	{ "item_rate_1",				       &battle_config.item_rate_1				},
+	{ "item_rate_10",				       &battle_config.item_rate_10				},
+	{ "item_rate_100",				       &battle_config.item_rate_100				},
+	{ "item_rate_1000",				       &battle_config.item_rate_1000			},
+	{ "item_rate_1_min",				   &battle_config.item_rate_1_min			},
+	{ "item_rate_1_max",				   &battle_config.item_rate_1_max			},
+	{ "item_rate_10_min",				   &battle_config.item_rate_10_min			},
+	{ "item_rate_10_max",				   &battle_config.item_rate_10_max			},
+	{ "item_rate_100_min",				   &battle_config.item_rate_100_min			},
+	{ "item_rate_100_max",				   &battle_config.item_rate_100_max			},
+	{ "item_rate_1000_min",				   &battle_config.item_rate_1000_min		},
+	{ "item_rate_1000_max",				   &battle_config.item_rate_1000_max		},
 	{ "item_rate_common",                  &battle_config.item_rate_common	},	// Added by RoVeRT
 	{ "item_rate_equip",                   &battle_config.item_rate_equip	},
 	{ "item_rate_card",                    &battle_config.item_rate_card	},	// End Addition
@@ -5362,6 +5418,11 @@ void battle_set_defaults() {
 	battle_config.natural_heal_skill_interval=10000;
 	battle_config.natural_heal_weight_rate=50;
 	battle_config.item_name_override_grffile=1;
+	battle_config.item_equip_override_grffile=1;	// [Celest]
+	battle_config.item_slots_override_grffile=1;	// [Celest]
+	battle_config.indoors_override_grffile=1;	// [Celest]
+	battle_config.skill_sp_override_grffile=1;	// [Celest]
+	battle_config.cardillust_read_grffile=1;	// [Celest]	
 	battle_config.arrow_decrement=1;
 	battle_config.max_aspd = 199;
 	battle_config.max_hp = 32500;
@@ -5405,7 +5466,6 @@ void battle_set_defaults() {
 	battle_config.mob_changetarget_byskill = 0;
 	battle_config.pc_attack_direction_change = 1;
 	battle_config.monster_attack_direction_change = 1;
-	battle_config.pc_undead_nofreeze = 0;
 	battle_config.pc_land_skill_limit = 1;
 	battle_config.monster_land_skill_limit = 1;
 	battle_config.party_skill_penalty = 1;
@@ -5437,6 +5497,26 @@ void battle_set_defaults() {
 	battle_config.invite_request_check = 1;
 	battle_config.skill_removetrap_type = 0;
 	battle_config.disp_experience = 0;
+	battle_config.castle_defense_rate = 100;
+	battle_config.riding_weight = 0;
+	battle_config.hp_rate = 100;
+	battle_config.sp_rate = 100;
+	battle_config.gm_can_drop_lv = 0;
+	battle_config.disp_hpmeter = 0;
+	battle_config.bone_drop = 0;
+	battle_config.item_rate_details = 0;
+	battle_config.item_rate_1 = 100;
+	battle_config.item_rate_10 = 100;
+	battle_config.item_rate_100 = 100;
+	battle_config.item_rate_1000 = 100;
+	battle_config.item_rate_1_min = 1;
+	battle_config.item_rate_1_max = 9;
+	battle_config.item_rate_10_min = 10;
+	battle_config.item_rate_10_max = 99;
+	battle_config.item_rate_100_min = 100;
+	battle_config.item_rate_100_max = 999;
+	battle_config.item_rate_1000_min = 1000;
+	battle_config.item_rate_1000_max = 10000;
 	battle_config.item_rate_common = 100;
 	battle_config.item_rate_equip = 100;
 	battle_config.item_rate_card = 100;
@@ -5530,6 +5610,10 @@ void battle_validate_conf() {
 		battle_config.max_aspd = 10;
 	if(battle_config.max_aspd > 1000)
 		battle_config.max_aspd = 1000;
+	if(battle_config.hp_rate < 0)
+		battle_config.hp_rate = 1;
+	if(battle_config.sp_rate < 0)
+		battle_config.sp_rate = 1;
 	if(battle_config.max_hp > 1000000)
 		battle_config.max_hp = 1000000;
 	if(battle_config.max_hp < 100)

+ 13 - 1
src/map/battle.h

@@ -212,6 +212,11 @@ extern struct Battle_Config {
 	int natural_heal_skill_interval;
 	int natural_heal_weight_rate;
 	int item_name_override_grffile;
+	int indoors_override_grffile;	// [Celest]
+	int skill_sp_override_grffile;	// [Celest]
+	int cardillust_read_grffile;
+	int item_equip_override_grffile;
+	int item_slots_override_grffile;
 	int arrow_decrement;
 	int max_aspd;
 	int max_hp;
@@ -253,7 +258,6 @@ extern struct Battle_Config {
 	int mob_changetarget_byskill;
 	int pc_attack_direction_change;
 	int monster_attack_direction_change;
-	int pc_undead_nofreeze;
 	int pc_land_skill_limit;
 	int monster_land_skill_limit;
 	int party_skill_penalty;
@@ -314,6 +318,14 @@ extern struct Battle_Config {
 	int castle_defense_rate;
 	int riding_weight;
 	int backstab_bow_penalty;
+	int hp_rate;
+	int sp_rate;
+	int gm_can_drop_lv;
+	int disp_hpmeter;
+	int bone_drop;
+	int item_rate_details,item_rate_1,item_rate_10,item_rate_100,item_rate_1000;	//ドロップレート詳細
+	int item_rate_1_min,item_rate_10_min,item_rate_100_min,item_rate_1000_min;	//ドロップレート詳細min
+	int item_rate_1_max,item_rate_10_max,item_rate_100_max,item_rate_1000_max;	//ドロップレート詳細max
 
 	int night_at_start; // added by [Yor]
 	int day_duration; // added by [Yor]

+ 42 - 0
src/map/clif.c

@@ -2387,6 +2387,8 @@ int clif_updatestatus(struct map_session_data *sd,int type)
 		break;
 	case SP_HP:
 		WFIFOL(fd,4)=sd->status.hp;
+		if(battle_config.disp_hpmeter)
+			clif_hpmeter(sd);
 		break;
 	case SP_SP:
 		WFIFOL(fd,4)=sd->status.sp;
@@ -5773,6 +5775,46 @@ int clif_party_hp(struct party *p,struct map_session_data *sd)
 //		printf("clif_party_hp %d\n",sd->status.account_id);
 	return 0;
 }
+/*==========================================
+ * GMへ場所とHP通知
+ *------------------------------------------
+ */
+int clif_hpmeter(struct map_session_data *sd)
+{
+	struct map_session_data *md;
+	unsigned char buf[16];
+	unsigned char buf2[16];
+	int i;
+	
+	nullpo_retr(0, sd);
+
+	WBUFW(buf,0)=0x107;
+	WBUFL(buf,2)=sd->bl.id;
+	WBUFW(buf,6)=sd->bl.x;
+	WBUFW(buf,8)=sd->bl.y;
+
+	for(i=0;i<fd_max;i++){
+		if(session[i] && (md=session[i]->session_data) && md->state.auth &&
+			md->bl.m == sd->bl.m && pc_isGM(md) && sd != md){
+			memcpy(WFIFOP(i,0),buf,packet_len_table[0x107]);
+			WFIFOSET(i,packet_len_table[0x107]);
+		}
+	}
+	
+	WBUFW(buf2,0)=0x106;
+	WBUFL(buf2,2)=sd->status.account_id;
+	WBUFW(buf2,6)=(sd->status.hp > 0x7fff)? 0x7fff:sd->status.hp;
+	WBUFW(buf2,8)=(sd->status.max_hp > 0x7fff)? 0x7fff:sd->status.max_hp;
+	for(i=0;i<fd_max;i++){
+		if(session[i] && (md=session[i]->session_data) && md->state.auth &&
+			md->bl.m == md->bl.m && pc_isGM(md) && sd != md){
+			memcpy(WFIFOP(i,0),buf2,packet_len_table[0x106]);
+			WFIFOSET(i,packet_len_table[0x106]);
+		}
+	}
+	
+	return 0;
+}
 /*==========================================
  * パーティ場所移動(未使用)
  *------------------------------------------

+ 1 - 0
src/map/clif.h

@@ -218,6 +218,7 @@ int clif_party_message(struct party *p,int account_id,char *mes,int len);
 int clif_party_move(struct party *p,struct map_session_data *sd,int online);
 int clif_party_xy(struct party *p,struct map_session_data *sd);
 int clif_party_hp(struct party *p,struct map_session_data *sd);
+int clif_hpmeter(struct map_session_data *sd);
 
 // guild
 int clif_guild_created(struct map_session_data *sd,int flag);

+ 10 - 3
src/map/guild.c

@@ -1191,10 +1191,17 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
 	int flag,const char *name1,const char *name2)
 {
 	struct guild *g[2];
-	int guild_id[2]={guild_id1,guild_id2};
-	const char *guild_name[2]={name1,name2};
-	struct map_session_data *sd[2]={map_id2sd(account_id1),map_id2sd(account_id2)};
+	int guild_id[2];
+	const char *guild_name[2];
+	struct map_session_data *sd[2];
 	int j,i;
+	
+	guild_id[0] = guild_id1;
+	guild_id[1] = guild_id2;
+	guild_name[0] = name1;
+	guild_name[1] = name2;
+	sd[0] = map_id2sd(account_id1);
+	sd[1] = map_id2sd(account_id2);
 
 	g[0]=guild_search(guild_id1);
 	g[1]=guild_search(guild_id2);

+ 112 - 76
src/map/itemdb.c

@@ -40,6 +40,9 @@ static int itemdb_read_sqldb(void);
 static int itemdb_read_randomitem();
 static int itemdb_read_itemavail(void);
 static int itemdb_read_itemnametable(void);
+static int itemdb_read_itemslottable(void);
+static int itemdb_read_itemslotcounttable(void);
+static int itemdb_read_cardillustnametable(void);
 static int itemdb_read_noequip(void);
 static int itemdb_read_norefine(void);
 void itemdb_reload(void);
@@ -99,14 +102,15 @@ int itemdb_searchrandomid(int flags)
 	struct {
 		int nameid,count;
 		struct random_item_data *list;
-	} data[] ={
-		{ 0,0,NULL },
-		{ blue_box_default	,blue_box_count		,blue_box	 },
-		{ violet_box_default,violet_box_count	,violet_box	 },
-		{ card_album_default,card_album_count	,card_album	 },
-		{ gift_box_default	,gift_box_count		,gift_box	 },
-		{ scroll_default	,scroll_count		,scroll		 },
-	};
+	} data[6];
+
+	// for BCC32 compile error
+	data[0].nameid = 0;						data[0].count = 0; 					data[0].list = NULL;
+	data[1].nameid = blue_box_default;		data[1].count = blue_box_count;		data[1].list = blue_box;
+	data[2].nameid = violet_box_default;	data[2].count = violet_box_count;	data[2].list = violet_box;
+	data[3].nameid = card_album_default;	data[3].count = card_album_count;	data[3].list = card_album;
+	data[4].nameid = gift_box_default;		data[4].count = gift_box_count;		data[4].list = gift_box;
+	data[5].nameid = scroll_default;		data[5].count = scroll_count;		data[5].list = scroll;
 
 	if(flags>=1 && flags<=5){
 		nameid=data[flags].nameid;
@@ -239,67 +243,40 @@ int itemdb_isdropable(int nameid)
 	return 1;
 }
 
-//
-// 初期化
-//
-/*==========================================
- *
- *------------------------------------------
- */
-static int itemdb_read_itemslottable(void)
-{
-	char *buf,*p;
-	int s;
-
-	buf=grfio_read("data\\itemslottable.txt");
-	if(buf==NULL)
-		return -1;
-	s=grfio_size("data\\itemslottable.txt");
-	buf[s]=0;
-	for(p=buf;p-buf<s;){
-		int nameid,equip;
-		sscanf(p,"%d#%d#",&nameid,&equip);
-		itemdb_search(nameid)->equip=equip;
-		p=strchr(p,10);
-		if(!p) break;
-		p++;
-		p=strchr(p,10);
-		if(!p) break;
-		p++;
-	}
-	free(buf);
-
-	return 0;
-}
-
-#ifndef TXT_ONLY
 /*====================================
  * Removed item_value_db, don't re-add
  *------------------------------------
  */
 static void itemdb_read(void)
 {
-	itemdb_read_itemslottable();
-
-	if (db_use_sqldbs)
-	{
-		itemdb_read_sqldb();
-    }
-    else
-    {
+	#ifndef TXT_ONLY
+		if (db_use_sqldbs)
+		{
+			itemdb_read_sqldb();
+		}
+		else
+		{
+			itemdb_readdb();
+		}
+	/* not TXT_ONLY */
+	#else
 		itemdb_readdb();
-    }
+	#endif /* TXT_ONLY */
 
 	itemdb_read_randomitem();
 	itemdb_read_itemavail();
 	itemdb_read_noequip();
 	itemdb_read_norefine();
-
-	if (!battle_config.item_name_override_grffile)
+	if (battle_config.cardillust_read_grffile)
+		itemdb_read_cardillustnametable();
+	if (battle_config.item_equip_override_grffile)
+		itemdb_read_itemslottable();
+	if (battle_config.item_slots_override_grffile)
+		itemdb_read_itemslotcounttable();
+	if (battle_config.item_name_override_grffile)
 		itemdb_read_itemnametable();
 }
 
-#endif /* not TXT_ONLY */
 /*==========================================
  * アイテムデータベースの読み込み
  *------------------------------------------
@@ -559,7 +536,7 @@ static int itemdb_read_itemnametable(void)
 
 	return 0;
 }
-#ifdef TXT_ONLY
+
 /*==========================================
  * カードイラストのリソース名前テーブルを読み込む
  *------------------------------------------
@@ -595,7 +572,74 @@ static int itemdb_read_cardillustnametable(void)
 
 	return 0;
 }
-#endif /* TXT_ONLY */
+
+//
+// 初期化
+//
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int itemdb_read_itemslottable(void)
+{
+	char *buf,*p;
+	int s;
+
+	buf=grfio_read("data\\itemslottable.txt");
+	if(buf==NULL)
+		return -1;
+	s=grfio_size("data\\itemslottable.txt");
+	buf[s]=0;
+	for(p=buf;p-buf<s;){
+		int nameid,equip;
+		sscanf(p,"%d#%d#",&nameid,&equip);
+		itemdb_search(nameid)->equip=equip;
+		p=strchr(p,10);
+		if(!p) break;
+		p++;
+		p=strchr(p,10);
+		if(!p) break;
+		p++;
+	}
+	free(buf);
+	sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslottable.txt");
+	ShowStatus(tmp_output);
+
+	return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+static int itemdb_read_itemslotcounttable(void)
+{
+	char *buf,*p;
+	int s;
+
+	buf=grfio_read("data\\itemslotcounttable.txt");
+	if(buf==NULL)
+		return -1;
+	s=grfio_size("data\\itemslotcounttable.txt");
+	buf[s]=0;
+	for(p=buf;p-buf<s;){
+		int nameid,slot;
+		sscanf(p,"%d#%d#",&nameid,&slot);
+		itemdb_search(nameid)->slot=slot;
+		p=strchr(p,10);
+		if(!p) break;
+		p++;
+		p=strchr(p,10);
+		if(!p) break;
+		p++;
+	}
+	free(buf);
+	sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","data\\itemslotcounttable.txt");
+	ShowStatus(tmp_output);
+
+	return 0;
+}
+
 /*==========================================
  * 装備制限ファイル読み出し
  *------------------------------------------
@@ -650,8 +694,18 @@ static int itemdb_read_norefine(void)
 	struct item_data *id;
 	// To-do: let it read from a text file later
 	int cant_refine[] = {
-		0, 1243, 1530, 2110, 2112, 2264, 2298, 2352, 2410, 2413,
-		2414, 2509, 2510, 5008, 5046, 5049, 5050, 5053, 5055, 5098
+		1243, 1530, 2110, 2112, 2201, 2202, 2203, 2204, 2205, 2210,
+		2212, 2218, 2219, 2237, 2238, 2239, 2240, 2241, 2242, 2243,
+		2250, 2253, 2260, 2262, 2263, 2264, 2265, 2266, 2267, 2268,
+		2269, 2270, 2271, 2276, 2278, 2279, 2281, 2282, 2286, 2288,
+		2289, 2290, 2291, 2292, 2293, 2295, 2296, 2297, 2298, 2352,
+		2410, 2413, 2414, 2509, 2510, 2601, 2602, 2603, 2604, 2605,
+		2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616,
+		2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626,
+		2627, 2628, 2629, 2630, 2631, 2634, 2635, 2636, 2637, 2638,
+		2639, 2640, 5004, 5005, 5006, 5008, 5014, 5015, 5037, 5039,
+		5040, 5043, 5046, 5049, 5050, 5051, 5053, 5054, 5055, 5058,
+		5068, 5074, 5085, 5086, 5087, 5088, 5089, 5090, 5096, 5098, 0
 	};
 
 	for (i=0; i < (int)(sizeof(cant_refine) / sizeof(cant_refine[0])); i++) {
@@ -885,24 +939,6 @@ void itemdebugtxt()
 	fclose(dfp);
 }
 */
-#ifdef TXT_ONLY
-/*====================================
- * Removed item_value_db, don't re-add
- *------------------------------------
- */
-static void itemdb_read(void)
-{
-	itemdb_read_itemslottable();
-	itemdb_readdb();
-	itemdb_read_randomitem();
-	itemdb_read_itemavail();
-	itemdb_read_noequip();
-	itemdb_read_norefine();
-	itemdb_read_cardillustnametable();
-	if (!battle_config.item_name_override_grffile)
-		itemdb_read_itemnametable();
-}
-#endif /* TXT_ONLY */
 /*==========================================
  *
  *------------------------------------------

+ 14 - 2
src/map/map.h

@@ -163,6 +163,7 @@ struct map_session_data {
 	struct mmo_charstatus status;
 	struct item_data *inventory_data[MAX_INVENTORY];
 	short equip_index[11];
+	unsigned short unbreakable_equip;
 	int weight,max_weight;
 	int cart_weight,cart_max_weight,cart_num,cart_max_num;
 	char mapname[24];
@@ -237,6 +238,7 @@ struct map_session_data {
 	int watk_,watk_2,atkmods_[3],addele_[10],addrace_[12],addsize_[3];	//二刀流のために追加
 	int atk_ele_,star_,overrefine_;				//二刀流のために追加
 	int base_atk,atk_rate;
+	int weapon_atk[16],weapon_atk_rate[16];
 	int arrow_atk,arrow_ele,arrow_cri,arrow_hit,arrow_range;
 	int arrow_addele[10],arrow_addrace[12],arrow_addsize[3],arrow_addeff[10],arrow_addeff2[10];
 	int nhealhp,nhealsp,nshealhp,nshealsp,nsshealhp,nsshealsp;
@@ -487,6 +489,14 @@ enum { NONE_ATTACKABLE,ATTACKABLE };
 
 enum { ATK_LUCKY=1,ATK_FLEE,ATK_DEF};	// 囲まれペナルティ計算用
 
+// 装備コード
+enum {
+	EQP_WEAPON		= 0x0002,		// 右手
+	EQP_ARMOR		= 0x0010,		// 体
+	EQP_SHIELD		= 0x0020,		// 左手
+	EQP_HELM		= 0x0100,		// 頭上段
+};
+
 struct map_data {
 	char name[24];
 	unsigned char *gat;	// NULLなら下のmap_data_other_serverとして扱う
@@ -592,10 +602,12 @@ enum {
 	SP_MAGIC_DAMAGE_RETURN,SP_RANDOM_ATTACK_INCREASE,SP_ALL_STATS,SP_AGI_VIT,SP_AGI_DEX_STR,SP_PERFECT_HIDE, // 1071-1076
 	SP_DISGUISE,SP_CLASSCHANGE, // 1077-1078
 	SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1079-1080
+	SP_WEAPON_ATK,SP_WEAPON_ATK_RATE, // 1081-1082
 
 	SP_RESTART_FULL_RECORVER=2000,SP_NO_CASTCANCEL,SP_NO_SIZEFIX,SP_NO_MAGIC_DAMAGE,SP_NO_WEAPON_DAMAGE,SP_NO_GEMSTONE, // 2000-2005
-	SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, // 2006-2010
-	SP_LONG_ATK_RATE // 2011 - celest
+	SP_NO_CASTCANCEL2,SP_INFINITE_ENDURE,SP_UNBREAKABLE_WEAPON,SP_UNBREAKABLE_ARMOR, SP_UNBREAKABLE_HELM, 
+	SP_UNBREAKABLE_SHIELD, // 2006-2011
+	SP_LONG_ATK_RATE // 2012 - celest
 };
 
 enum {

+ 50 - 8
src/map/mob.c

@@ -37,6 +37,8 @@
 
 struct mob_db mob_db[2001];
 
+#define CLASSCHANGE_BOSS_NUM 21
+
 /*==========================================
  * Local prototype declaration   (only required thing)
  *------------------------------------------
@@ -2093,7 +2095,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 	int mvp_damage,max_hp;
 	unsigned int tick = gettick();
 	struct map_session_data *mvp_sd = NULL, *second_sd = NULL,*third_sd = NULL;
-	double dmg_rate,tdmg,temp;
+	double tdmg,temp;
 	struct item item;
 	int ret;
 	int drop_rate;
@@ -2348,12 +2350,12 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		}
 	}
 
-        // [MouseJstr]
-        if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
+	// [MouseJstr]
+	if((map[md->bl.m].flag.pvp == 0) || (battle_config.pvp_exp == 1)) {
 
-	if((double)max_hp < tdmg)
+/*	if((double)max_hp < tdmg)
 		dmg_rate = ((double)max_hp) / tdmg;
-	else dmg_rate = 1;
+	else dmg_rate = 1;*/
 
 	// 経験値の分配
 	for(i=0;i<DAMAGELOG_SIZE;i++){
@@ -2363,7 +2365,8 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 		if(tmpsd[i]==NULL || tmpsd[i]->bl.m != md->bl.m)
 			continue;
 /* jAthena's exp formula
-		per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
+	//	per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./((double)max_hp) * dmg_rate;
+		per = ((double)md->dmglog[i].dmg)*(9.+(double)((count > 6)? 6:count))/10./tdmg;
 		temp = ((double)mob_db[md->class].base_exp * (double)battle_config.base_exp_rate / 100. * per);
 		base_exp = (temp > 2147483647.)? 0x7fffffff:(int)temp;
 		if(mob_db[md->class].base_exp > 0 && base_exp < 1) base_exp = 1;
@@ -2891,7 +2894,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,int flag)
 
 	if(value[0]<=1000 || value[0]>MAX_MOB_DB)	// 値が異常なら召喚を止める
 		return 0;
-	while(count < 5 && value[count] > 1000 && value[count] <= 2000) count++;
+	while(count < 21 && value[count] > 1000 && value[count] <= 2000) count++;
 	if(count < 1) return 0;
 
 	for(k=0;k<count;k++) {
@@ -3884,7 +3887,46 @@ static int mob_readdb(void)
 					ratemin = battle_config.item_drop_common_min;
 					ratemax = battle_config.item_drop_common_max;
 				}
-				rate = (rate / 100) * atoi(str[30+i*2]);
+				if (battle_config.item_rate_details == 1) {	//ドロップレート詳細項目が1の時 レート=x/100倍
+					if (rate < 10)
+						rate = rate * battle_config.item_rate_1/100;
+					else if (rate >= 10 && rate < 100)
+						rate = rate * battle_config.item_rate_10/100;
+					else if (rate >= 100 && rate < 1000)
+						rate = rate * battle_config.item_rate_100/100;
+					else rate = rate * battle_config.item_rate_1000/100;
+				}
+				else if (battle_config.item_rate_details == 2) {	//ドロップレート詳細項目が2の時 レート=x/100倍 min max 指定
+					if (rate >= 1 && rate < 10) {
+						if (rate * battle_config.item_rate_1/100 < battle_config.item_rate_1_min)
+							rate = battle_config.item_rate_1_min;
+						else if (rate * battle_config.item_rate_1/100 > battle_config.item_rate_1_max)
+							rate = battle_config.item_rate_1_max;
+						else rate = rate * battle_config.item_rate_1/100;
+					}
+					else if (rate >= 10 && rate < 100) {
+						if (rate * battle_config.item_rate_10/100 < battle_config.item_rate_10_min)
+							rate = battle_config.item_rate_10_min;
+						else if (rate * battle_config.item_rate_10/100 > battle_config.item_rate_10_max)
+							rate = battle_config.item_rate_10_max;
+						else rate = rate * battle_config.item_rate_10/100;
+					}
+					else if (rate >= 100 && rate < 1000) {
+						if (rate * battle_config.item_rate_100/100 < battle_config.item_rate_100_min)
+							rate = battle_config.item_rate_100_min;
+						else if (rate * battle_config.item_rate_100/100 > battle_config.item_rate_100_max)
+							rate = battle_config.item_rate_100_max;
+						else rate = rate * battle_config.item_rate_100/100;
+					}
+					else if (rate >= 1000) {
+						if (rate * battle_config.item_rate_1000/100 < battle_config.item_rate_1000_min)
+							rate = battle_config.item_rate_1000_min;
+						else if (rate * battle_config.item_rate_1000/100 > battle_config.item_rate_1000_max)
+							rate = battle_config.item_rate_1000_max;
+						else rate = rate * battle_config.item_rate_1000/100;
+					}
+				}
+				rate = rate * atoi(str[30+i*2])/100;
 				rate = (rate < ratemin)? ratemin: (rate > ratemax)? ratemax: rate;
 				mob_db[class].dropitem[i].p = rate;
 			}

+ 2 - 1
src/map/npc.c

@@ -2303,7 +2303,8 @@ int do_init_npc(void)
 	char c = '-';
 
 	// indoorrswtable.txt and etcinfo.txt [Celest]
-	npc_read_indoors();
+	if (battle_config.indoors_override_grffile)
+		npc_read_indoors();
 	//npc_read_weather();
 
 	ev_db=strdb_init(24);

+ 120 - 3
src/map/pc.c

@@ -588,6 +588,52 @@ int pc_isequip(struct map_session_data *sd,int n)
 	return 1;
 }
 
+//装備破壊
+int pc_break_equip(struct map_session_data *sd, unsigned short where)
+{
+	struct item_data* item;
+	int i;
+	int sc;
+	char output[255];	
+
+	if(sd == NULL)
+		return -1;
+	if(sd->unbreakable_equip & where)
+		return 0;
+	switch (where) {
+		case EQP_WEAPON:
+			sc = SC_CP_WEAPON;
+			break;
+		case EQP_ARMOR:
+			sc = SC_CP_ARMOR;
+			break;
+		case EQP_SHIELD:
+			sc = SC_CP_SHIELD;
+			break;
+		case EQP_HELM:
+			sc = SC_CP_HELM;
+			break;
+		default:
+			return 0;
+	}
+	if( sd->sc_data && sd->sc_data[sc].timer != -1 )
+		return 0;
+
+	for (i=0;i<MAX_INVENTORY;i++) {
+		if (sd->status.inventory[i].equip & where) {
+			item=sd->inventory_data[i];
+			sd->status.inventory[i].attribute = 1;
+			pc_unequipitem(sd,i,0);
+			break;
+		}
+	}
+	sprintf(output, "%s has broken.",item->jname);
+	clif_emotion(&sd->bl,23);
+	clif_displaymessage(sd->fd, output);
+	clif_equiplist(sd);
+	return 0;
+}
+
 /*==========================================
  * Weapon Breaking [Valaris]
  *------------------------------------------
@@ -1230,8 +1276,8 @@ int pc_calcstatus(struct map_session_data* sd,int first)
 	sd->matk1 =0;
 	sd->matk2 =0;
 	sd->speed = DEFAULT_WALK_SPEED ;
-	sd->hprate=100;
-	sd->sprate=100;
+	sd->hprate=battle_config.hp_rate;
+	sd->sprate=battle_config.sp_rate;
 	sd->castrate=100;
 	sd->dsprate=100;
 	sd->base_atk=0;
@@ -1254,6 +1300,8 @@ int pc_calcstatus(struct map_session_data* sd,int first)
 	memset(&sd->special_state,0,sizeof(sd->special_state));
 	memset(sd->weapon_coma_ele,0,sizeof(sd->weapon_coma_ele));
 	memset(sd->weapon_coma_race,0,sizeof(sd->weapon_coma_race));
+	memset(sd->weapon_atk,0,sizeof(sd->weapon_atk));
+	memset(sd->weapon_atk_rate,0,sizeof(sd->weapon_atk_rate));
 
 	sd->watk_ = 0;			//二刀流用(?)
 	sd->watk_2 = 0;
@@ -1307,6 +1355,9 @@ int pc_calcstatus(struct map_session_data* sd,int first)
 	sd->short_weapon_damage_return = sd->long_weapon_damage_return = 0;
 	sd->magic_damage_return = 0; //AppleGirl Was Here
 	sd->random_attack_increase_add = sd->random_attack_increase_per = 0;
+	sd->hp_drain_value = sd->hp_drain_value_ = sd->sp_drain_value = sd->sp_drain_value_ = 0;
+	sd->unbreakable_equip = 0;
+
 
 	if(!sd->disguiseflag && sd->disguise) {
 		sd->disguise=0;
@@ -1549,6 +1600,10 @@ int pc_calcstatus(struct map_session_data* sd,int first)
 			if(sd->sc_data[SC_CHASEWALK].val4)
 				sd->paramb[0] += (1<<(sd->sc_data[SC_CHASEWALK].val1-1)); // increases strength after 10 seconds
 		}
+		if(sd->sc_data[SC_SLOWDOWN].timer!=-1)
+			sd->speed = sd->speed*150/100;
+		if(sd->sc_data[SC_SPEEDUP0].timer!=-1)
+			sd->speed -= sd->speed*25/100;
 		if(sd->sc_data[SC_BLESSING].timer!=-1){	// ブレッシング
 			sd->paramb[0]+= sd->sc_data[SC_BLESSING].val1;
 			sd->paramb[3]+= sd->sc_data[SC_BLESSING].val1;
@@ -2210,6 +2265,10 @@ int pc_calcspeed (struct map_session_data *sd)
 		}
 		if(sd->sc_data[SC_CURSE].timer!=-1)
 			sd->speed += 450;
+		if(sd->sc_data[SC_SLOWDOWN].timer!=-1)
+			sd->speed = sd->speed*150/100;
+		if(sd->sc_data[SC_SPEEDUP0].timer!=-1)
+			sd->speed -= sd->speed*25/100;
 	}
 
 	if(sd->status.option&2 && (skill = pc_checkskill(sd,RG_TUNNELDRIVE))>0 )
@@ -2546,6 +2605,22 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		if(sd->state.lr_flag != 2)
 			sd->special_state.infinite_endure = 1;
 		break;
+	case SP_UNBREAKABLE_WEAPON:
+		if(sd->state.lr_flag != 2)
+			sd->unbreakable_equip |= EQP_WEAPON;
+		break;
+	case SP_UNBREAKABLE_ARMOR:
+		if(sd->state.lr_flag != 2)
+			sd->unbreakable_equip |= EQP_ARMOR;
+		break;
+	case SP_UNBREAKABLE_HELM:
+		if(sd->state.lr_flag != 2)
+			sd->unbreakable_equip |= EQP_HELM;
+		break;
+	case SP_UNBREAKABLE_SHIELD:
+		if(sd->state.lr_flag != 2)
+			sd->unbreakable_equip |= EQP_SHIELD;
+		break;
 	case SP_SPLASH_RANGE:
 		if(sd->state.lr_flag != 2 && sd->splash_range < val)
 			sd->splash_range = val;
@@ -2837,6 +2912,14 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 			sd->random_attack_increase_per += val;
 		}	
 		break;
+	case SP_WEAPON_ATK:
+		if(sd->state.lr_flag != 2)
+			sd->weapon_atk[type2]+=val;
+		break;
+	case SP_WEAPON_ATK_RATE:
+		if(sd->state.lr_flag != 2)
+			sd->weapon_atk_rate[type2]+=val;
+		break;
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
@@ -3203,7 +3286,8 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
 	    sd->status.inventory[n].amount < amount ||
 	    sd->trade_partner != 0 || sd->vender_id != 0 ||
 	    sd->status.inventory[n].amount <= 0 ||
-		itemdb_isdropable(sd->status.inventory[n].nameid) == 0) // Celest
+		itemdb_isdropable(sd->status.inventory[n].nameid) == 0 || // Celest
+		pc_candrop(sd,sd->status.inventory[n].nameid))
 		return 1;
 	map_addflooritem(&sd->status.inventory[n], amount, sd->bl.m, sd->bl.x, sd->bl.y, NULL, NULL, NULL, 0);
 	pc_delitem(sd, n, amount, 0);
@@ -3279,6 +3363,8 @@ int pc_isUseitem(struct map_session_data *sd,int n)
 
 	if(item == NULL)
 		return 0;
+	if(item->type != 0 && item->type != 2)
+		return 0;
 	if((nameid == 605) && map[sd->bl.m].flag.gvg)
 		return 0;
 	if(nameid == 601 && (map[sd->bl.m].flag.noteleport || map[sd->bl.m].flag.gvg)) {
@@ -3432,6 +3518,10 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount) {
 	nullpo_retr(0, sd);
 	nullpo_retr(0, item_data = &sd->status.inventory[idx]);
 
+	if(itemdb_isdropable(sd->status.inventory[idx].nameid) == 0)
+		return 1;
+	if(pc_candrop(sd,sd->status.inventory[idx].nameid)==1)
+		return 1;
 	if (item_data->nameid==0 || item_data->amount<amount || sd->vender_id)
 		return 1;
 	if (pc_cart_additem(sd,item_data,amount) == 0)
@@ -3836,6 +3926,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 					intif_save_petdata(sd->status.account_id,&sd->pet);
 				chrif_save(sd);
 				storage_storage_save(sd);
+				storage_delete(sd->status.account_id);
 				chrif_changemapserver(sd, mapname, x, y, ip, port);
 				return 0;
 			}
@@ -4174,6 +4265,8 @@ static int pc_walk(int tid,unsigned int tick,int id,int data)
 			i = 1;
 		sd->walktimer=add_timer(tick+i,pc_walk,id,sd->walkpath.path_pos);
 	}
+	if(battle_config.disp_hpmeter)
+		clif_hpmeter(sd);
 
 	return 0;
 }
@@ -5498,6 +5591,18 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	clif_updatestatus(sd,SP_HP);
 	pc_calcstatus(sd,0);
 
+	if(battle_config.bone_drop==2
+		|| (battle_config.bone_drop==1 && map[sd->bl.m].flag.pvp)){	// ドクロドロップ
+		struct item item_tmp;
+		memset(&item_tmp,0,sizeof(item_tmp));
+		item_tmp.nameid=7005;
+		item_tmp.identify=1;
+		item_tmp.card[0]=0x00fe;
+		item_tmp.card[1]=0;
+		*((unsigned long *)(&item_tmp.card[2]))=sd->char_id;	/* キャラID */
+		map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
+	}
+
 	// activate Steel body if a super novice dies at 99+% exp [celest]
 	if (s_class.job == 23) {
 		if ((i=pc_nextbaseexp(sd))<=0)
@@ -6286,6 +6391,18 @@ int pc_setriding(struct map_session_data *sd)
 	return 0;
 }
 
+/*==========================================
+ * アイテムドロップ可不可判定
+ *------------------------------------------
+ */
+int pc_candrop(struct map_session_data *sd,int item_id)
+{
+	int level;
+	if((level=pc_isGM(sd))>0 && level < battle_config.gm_can_drop_lv) // search only once [Celest]
+		return 1;
+	return 0;
+}
+
 /*==========================================
  * script用??の値を?む
  *------------------------------------------

+ 2 - 1
src/map/pc.h

@@ -162,7 +162,8 @@ int pc_divorce(struct map_session_data *sd);
 struct map_session_data *pc_get_partner(struct map_session_data *sd);
 int pc_set_gm_level(int account_id, int level);
 void pc_setstand(struct map_session_data *sd);
-
+int pc_break_equip(struct map_session_data *sd, unsigned short where);
+int pc_candrop(struct map_session_data *sd,int item_id);
 
 struct pc_base_job{
 	int job; //職業、ただし転生職や養子職の場合は元の職業を返す(廃プリ→プリ)

+ 63 - 1
src/map/script.c

@@ -274,6 +274,7 @@ int buildin_petloot(struct script_state *st); // pet looting [Valaris]
 int buildin_petheal(struct script_state *st); // pet healing [Valaris]
 int buildin_petmag(struct script_state *st); // pet magnificat [Valaris]
 int buildin_petskillattack(struct script_state *st); // pet skill attacks [Valaris]
+int buildin_skilleffect(struct script_state *st); // skill effects [Celest]
 int buildin_npcskilleffect(struct script_state *st); // skill effects for npcs [Valaris]
 int buildin_specialeffect(struct script_state *st); // special effect script [Valaris]
 int buildin_specialeffect2(struct script_state *st); // special effect script [Valaris]
@@ -292,6 +293,8 @@ int buildin_getmapxy(struct script_state *st);  //get map position for player/np
 int buildin_checkoption1(struct script_state *st); // [celest]
 int buildin_checkoption2(struct script_state *st); // [celest]
 int buildin_guildgetexp(struct script_state *st); // [celest]
+int buildin_skilluseid(struct script_state *st); // originally by Qamera [celest]
+int buildin_skillusepos(struct script_state *st); // originally by Qamera [celest]
 
 void push_val(struct script_stack *stack,int type,int val);
 int run_func(struct script_state *st);
@@ -481,6 +484,7 @@ struct {
 	{buildin_petheal,"petheal","iii"}, // [Valaris]
 	{buildin_petmag,"petmag","iiii"}, // [Valaris]
 	{buildin_petskillattack,"petskillattack","iiii"}, // [Valaris]
+	{buildin_skilleffect,"skilleffect","ii"}, // skill effect [Celest]
 	{buildin_npcskilleffect,"npcskilleffect","iiii"}, // npc skill effect [Valaris]
 	{buildin_specialeffect,"specialeffect","i"}, // npc skill effect [Valaris]
 	{buildin_specialeffect2,"specialeffect2","i"}, // skill effect on players[Valaris]
@@ -504,6 +508,9 @@ struct {
 	{buildin_checkoption1,"checkoption1","i"},
 	{buildin_checkoption2,"checkoption2","i"},
 	{buildin_guildgetexp,"guildgetexp","i"},
+	{buildin_skilluseid,"skilluseid","ii"}, // originally by Qamera [Celest]
+	{buildin_skilluseid,"doskill","ii"}, // since a lot of scripts would already use 'doskill'...
+	{buildin_skillusepos,"skillusepos","iiii"}, // [Celest]
 	{NULL,NULL,NULL},
 };
 int buildin_message(struct script_state *st); // [MouseJstr]
@@ -2323,7 +2330,8 @@ int buildin_getitem(struct script_state *st)
 			return 0;
 		if((flag = pc_additem(sd,&item_tmp,amount))) {
 			clif_additem(sd,0,0,flag);
-			map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
+			if(!pc_candrop(sd,nameid))
+				map_addflooritem(&item_tmp,amount,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0);
 		}
 	}
 
@@ -5827,6 +5835,24 @@ int buildin_petskillattack(struct script_state *st)
 
 	return 0;
 }
+
+/*==========================================
+ * Scripted skill effects [Celest]
+ *------------------------------------------
+ */
+int buildin_skilleffect(struct script_state *st)
+{
+	struct map_session_data *sd;
+	
+	int skillid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+	int skilllv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+	sd=script_rid2sd(st);
+	
+	clif_skill_nodamage(&sd->bl,&sd->bl,skillid,skilllv,1);
+
+	return 0;
+}
+
 /*==========================================
  * NPC skill effects [Valaris]
  *------------------------------------------
@@ -6284,6 +6310,42 @@ int buildin_getmapxy(struct script_state *st){
         return 0;
 }
 
+/*=====================================================
+ * Allows players to use a skill - by Qamera
+ *-----------------------------------------------------
+ */
+int buildin_skilluseid (struct script_state *st)
+{
+   int skid,sklv;
+   struct map_session_data *sd;
+
+   skid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+   sklv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+   sd=script_rid2sd(st);
+   skill_use_id(sd,sd->status.account_id,skid,sklv);
+
+   return 0;
+}
+
+/*=====================================================
+ * Allows players to use a skill on a position [Celest]
+ *-----------------------------------------------------
+ */
+int buildin_skillusepos(struct script_state *st)
+{
+   int skid,sklv,x,y;
+   struct map_session_data *sd;
+
+   skid=conv_num(st,& (st->stack->stack_data[st->start+2]));
+   sklv=conv_num(st,& (st->stack->stack_data[st->start+3]));
+   x=conv_num(st,& (st->stack->stack_data[st->start+4]));
+   y=conv_num(st,& (st->stack->stack_data[st->start+5]));
+
+   sd=script_rid2sd(st);
+   skill_use_pos(sd,x,y,skid,sklv);
+
+   return 0;
+}
 
 //
 // ŽÀ�s•”main

+ 145 - 141
src/map/skill.c

@@ -231,7 +231,8 @@ int SkillStatusChangeTable[]={	/* skill.h
 	SC_BASILICA,
 	-1,-1,-1,
 	SC_MAGICPOWER,
-	-1,-1,
+	-1,
+	SC_SACRIFICE,
 	SC_GOSPEL,
 /* 370- */
 	-1,-1,-1,-1,-1,-1,-1,-1,
@@ -2335,7 +2336,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	case LK_HEADCRUSH:	/* ヘッドクラッシュ */
 	case LK_JOINTBEAT:	/* ジョイントビ?ト */
 	case PA_PRESSURE:	/* プレッシャ? */
-	case PA_SACRIFICE:	/* サクリファイス */
+//	case PA_SACRIFICE:	/* サクリファイス */
 	case SN_SHARPSHOOTING:			/* シャ?プシュ?ティング */
 	case CG_ARROWVULCAN:			/* アロ?バルカン */
 	case ASC_BREAKER:				/* ソウルブレ?カ? */
@@ -2538,12 +2539,11 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 			/* 個別にダメ?ジを?える */
 			if(bl->id!=skill_area_temp[1])
 				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0x0500);
-		}
-		else {
-			int damage;
+		} else {
+/*			int damage;
 			map_freeblock_lock();
 			damage = skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
-			if(damage > 0) {
+			if(damage > 0) {*/
 				int i,c;	/* 他人から聞いた動きなので間違ってる可能性大&?率が?いっす>< */
 				c = skill_get_blewcount(skillid,skilllv);
 				if(map[bl->m].flag.gvg) c = 0;
@@ -2565,16 +2565,18 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 				skill_area_temp[1]=bl->id;
 				skill_area_temp[2]=bl->x;
 				skill_area_temp[3]=bl->y;
+				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
+
 				/* その後タ?ゲット以外の範??の敵全?に?理を行う */
 				map_foreachinarea(skill_area_sub,
 					bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,
 					src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
 					skill_castend_damage_id);
-				battle_damage(src,bl,damage,1);
+/*				battle_damage(src,bl,damage,1);
 				if(rdamage > 0)
 					battle_damage(bl,src,rdamage,0);
 			}
-			map_freeblock_unlock();
+			map_freeblock_unlock();*/
 		}
 		break;
 
@@ -2597,7 +2599,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	case WZ_EARTHSPIKE:			/* アーススパイク */
 	case AL_HEAL:				/* ヒール */
 	case AL_HOLYLIGHT:			/* ホーリーライト */
-	case MG_FROSTDIVER:			/* フロストダイバー */
+//	case MG_FROSTDIVER:			/* フロストダイバー */
 	case WZ_JUPITEL:			/* ユピテルサンダー */
 	case NPC_DARKJUPITEL:			/*闇ユピテル*/
 	case NPC_MAGICALATTACK:		/* MOB:魔法打?攻? */
@@ -2606,6 +2608,28 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 		skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 
+	case MG_FROSTDIVER:		/* フロストダイバー */
+	{
+		struct status_change *sc_data = battle_get_sc_data(bl);
+		int sc_def_mdef, rate, damage;
+		sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3);
+		rate = (skilllv*3+35)*sc_def_mdef/100-(battle_get_int(bl)+battle_get_luk(bl))/15;
+		rate = rate<=5?5:rate;
+		if (sc_data && sc_data[SC_FREEZE].timer != -1) {
+			skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
+		} else if (sd) {
+			clif_skill_fail(sd,skillid,0,0);
+			break;
+		}
+		damage = skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
+		if (battle_get_hp(bl) > 0 && damage > 0 && rand()%100 < rate) {
+			skill_status_change_start(bl,SC_FREEZE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
+		} else if (sd) {
+			clif_skill_fail(sd,skillid,0,0);
+		}
+		break;
+	}
+
 	case WZ_WATERBALL:			/* ウォ?タ?ボ?ル */
 		skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
 		if(skilllv>1)
@@ -2849,7 +2873,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 	struct mob_data *md=NULL;
 	struct mob_data *dstmd=NULL;
 	int i,abra_skillid=0,abra_skilllv;
-	int sc_def_vit,sc_def_mdef,strip_fix,strip_time,strip_per;
+	int sc_def_vit,sc_def_mdef,strip_time,strip_per;
 	int sc_dex,sc_luk;
 	//クラスチェンジ用ボスモンスタ?ID
 	int changeclass[]={1038,1039,1046,1059,1086,1087,1112,1115
@@ -2872,7 +2896,6 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 	sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
 	//sc_def_vit = 100 - (3 + battle_get_vit(bl) + battle_get_luk(bl)/3);
 	sc_def_mdef = 100 - (3 + battle_get_mdef(bl) + battle_get_luk(bl)/3);
-	strip_fix = battle_get_dex(src) - battle_get_dex(bl);
 
 	if(bl->type==BL_PC){
 		nullpo_retr(1, dstsd=(struct map_session_data *)bl);
@@ -2887,8 +2910,6 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 		sc_def_vit=0;
 	if(sc_def_mdef < 0)
 		sc_def_mdef=0;
-	if(strip_fix < 0)
-		strip_fix=0;
 
 	if(bl == NULL || bl->prev == NULL)
 		return 1;
@@ -3231,6 +3252,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 	case ST_REJECTSWORD:	/* リジェクトソ?ド */
 	case HW_MAGICPOWER:		/* 魔法力?幅 */
 	case PF_MEMORIZE:		/* メモライズ */
+	case PA_SACRIFICE:
 	case ASC_EDP:			// [Celest]
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
 		skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,skill_get_time(skillid,skilllv),0 );
@@ -3713,6 +3735,7 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 
 	case MG_STONECURSE:			/* スト?ンカ?ス */
 		{
+			struct status_change *sc_data = battle_get_sc_data(bl);
 			// Level 6-10 doesn't consume a red gem if it fails [celest]
 			int i, gem_flag = 1;
 			if (bl->type==BL_MOB && battle_get_mode(bl)&0x20) {
@@ -3722,7 +3745,12 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 			clif_skill_nodamage(src,bl,skillid,skilllv,1);
 			if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage )
 				break;
-			if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
+			if (sc_data && sc_data[SC_STONE].timer != -1) {
+				skill_status_change_end(bl,SC_STONE,-1);
+				if (sd)
+					clif_skill_fail(sd,skillid,0,0);
+			}
+			else if( rand()%100 < skilllv*4+20 && !battle_check_undead(battle_get_race(bl),battle_get_elem_type(bl)))
 				skill_status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
 			else if(sd) {
 				if (skilllv > 5) gem_flag = 0;
@@ -3876,105 +3904,67 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 		break;
 
 	case RG_STRIPWEAPON:		/* ストリップウェポン */
-		{
-			struct status_change *tsc_data = battle_get_sc_data(bl);
-			
-			if(tsc_data && tsc_data[SC_CP_WEAPON].timer != -1 )
+	case RG_STRIPSHIELD:		/* ストリップシールド */
+	case RG_STRIPARMOR:			/* ストリップアーマー */
+	case RG_STRIPHELM:			/* ストリップヘルム */
+	{
+		struct status_change *tsc_data = battle_get_sc_data(bl);
+		int scid, equip, strip_fix;
+		scid = SkillStatusChangeTable[skillid];
+		switch (skillid) {
+			case RG_STRIPWEAPON:
+				equip = EQP_WEAPON;
 				break;
-			strip_per = 5+2*skilllv+strip_fix/5;
-			strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
-			if(rand()%100 < strip_per){
-				clif_skill_nodamage(src,bl,skillid,skilllv,1);
-				skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
-				if(dstsd){
-					for(i=0;i<MAX_INVENTORY;i++){
-						if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0002){
-							pc_unequipitem(dstsd,i,3);
-							break;
-						}
-					}
-				}
-			}
-		}
-		break;
-
-	case RG_STRIPSHIELD:		/* ストリップシ?ルド */
-		{
-			struct status_change *tsc_data = battle_get_sc_data(bl);
-			
-			if(tsc_data && tsc_data[SC_CP_SHIELD].timer != -1 )
+			case RG_STRIPSHIELD:
+				equip = EQP_SHIELD;
 				break;
-			strip_per = 5+2*skilllv+strip_fix/5;
-			strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
-			if(rand()%100 < strip_per){
-				clif_skill_nodamage(src,bl,skillid,skilllv,1);
-				skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
-				if(dstsd){
-					for(i=0;i<MAX_INVENTORY;i++){
-						if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0020){
-							pc_unequipitem(dstsd,i,3);
-							break;
-						}
-					}
-				}
-			}
-		}
-		break;
-
-	case RG_STRIPARMOR:			/* ストリップア?マ? */
-		{
-			struct status_change *tsc_data = battle_get_sc_data(bl);
-			
-			if(tsc_data && tsc_data[SC_CP_ARMOR].timer != -1 )
+			case RG_STRIPARMOR:
+				equip = EQP_ARMOR;
 				break;
-			strip_per = 5+2*skilllv+strip_fix/5;
-			strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
-			if(rand()%100 < strip_per){
-				clif_skill_nodamage(src,bl,skillid,skilllv,1);
-				skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
-				if(dstsd){
-					for(i=0;i<MAX_INVENTORY;i++){
-						if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0010){
-							pc_unequipitem(dstsd,i,3);
-							break;
-						}
-					}
-				}
-			}
+			case RG_STRIPHELM:
+				equip = EQP_HELM;
+				break;
+			default:
+				return 1;
 		}
-		break;
 
-	case RG_STRIPHELM:			/* ストリップヘルム */
-		{
-			struct status_change *tsc_data = battle_get_sc_data(bl);
-			
-			if(tsc_data && tsc_data[SC_CP_HELM].timer != -1 )
-				break;
-			strip_per = 5+2*skilllv+strip_fix/5;
-			strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
-			if(rand()%100 < strip_per){
-				clif_skill_nodamage(src,bl,skillid,skilllv,1);
-				skill_status_change_start(bl,SkillStatusChangeTable[skillid],skilllv,0,0,0,strip_time,0 );
-				if(dstsd){
-					for(i=0;i<MAX_INVENTORY;i++){
-						if(dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & 0x0100){
-							pc_unequipitem(dstsd,i,3);
-							break;
-						}
-					}
+		if (tsc_data && tsc_data[scid].timer != -1)
+			break;
+
+		strip_fix = battle_get_dex(src) - battle_get_dex(bl);
+		if(strip_fix < 0)
+			strip_fix=0;
+		strip_per = 5+2*skilllv+strip_fix/5;
+		if (rand()%100 >= strip_per)
+			break;
+
+		if (dstsd) {
+			for (i=0;i<MAX_INVENTORY;i++) {
+				if (dstsd->status.inventory[i].equip && dstsd->status.inventory[i].equip & equip){
+					pc_unequipitem(dstsd,i,0);
+					break;
 				}
 			}
+			if (i == MAX_INVENTORY)
+				break;
 		}
+		clif_skill_nodamage(src,bl,skillid,skilllv,1);
+		strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
+		skill_status_change_start(bl,scid,skilllv,0,0,0,strip_time,0 );
 		break;
+	}
 
 	// Full Strip [Celest]
 	case ST_FULLSTRIP:
 		{
 			struct status_change *tsc_data = battle_get_sc_data(bl);
-			int c=0, i, j;
+			int c=0, i, j, strip_fix;
 			int striplist[2][4] = { { 0, 0, 0, 0 },
 				{ 0x0002, 0x0020, 0x0010, 0x0100 } };
 
+			strip_fix = battle_get_dex(src) - battle_get_dex(bl);
+			if(strip_fix < 0)
+				strip_fix=0;
 			strip_per = 5+2*skilllv+strip_fix/5;
 			strip_time = skill_get_time(skillid,skilllv)+strip_fix/2;
 			for (i=0; i<4; i++) {
@@ -5170,13 +5160,14 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma
 
 	case AL_WARP:			/* ワ?プポ?タル */
 		{
-			const struct point *p[]={
-				&sd->status.save_point,&sd->status.memo_point[0],
-				&sd->status.memo_point[1],&sd->status.memo_point[2],
-			};
+			const struct point *p[4];
 			struct skill_unit_group *group;
 			int i;
 			int maxcount=0;
+			p[0] = &sd->status.save_point;
+			p[1] = &sd->status.memo_point[0];
+			p[2] = &sd->status.memo_point[1];
+			p[3] = &sd->status.memo_point[2];
 
 			if((maxcount = skill_get_maxcount(sd->skillid)) > 0) {
 				int c;
@@ -7390,6 +7381,11 @@ int skill_castfix( struct block_list *bl, int time )
 
 	castnodex=skill_get_castnodex(skill, lv);
 
+	/* サフラギウム */
+	if(sc_data && sc_data[SC_SUFFRAGIUM].timer!=-1 )
+		time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
+			skill_status_change_end( bl, SC_SUFFRAGIUM, -1);
+
 	if(time==0)
 		return 0;
 	if(castnodex > 0 && bl->type==BL_PC)
@@ -7400,17 +7396,10 @@ int skill_castfix( struct block_list *bl, int time )
 		time=time*battle_config.cast_rate/100;
 	}
 
-	/* サフラギウム */
-	if(sc_data) {
-		if ( sc_data[SC_SUFFRAGIUM].timer!=-1 ){
-			time=time*(100-sc_data[SC_SUFFRAGIUM].val1*15)/100;
-			skill_status_change_end( bl, SC_SUFFRAGIUM, -1);
-		}
-		/* ブラギの詩 */
-		if( sc_data[SC_POEMBRAGI].timer!=-1 )
-			time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
-					+(sc_data[SC_POEMBRAGI].val3>>16)))/100;
-	}
+	/* ブラギの詩 */
+	if(sc_data && sc_data[SC_POEMBRAGI].timer!=-1)
+		time=time*(100-(sc_data[SC_POEMBRAGI].val1*3+sc_data[SC_POEMBRAGI].val2
+			+(sc_data[SC_POEMBRAGI].val3>>16)))/100;
 
 	return (time>0)?time:0;
 }
@@ -7426,7 +7415,8 @@ int skill_delayfix( struct block_list *bl, int time )
 
 	sc_data = battle_get_sc_data(bl);
 	if(time<=0)
-		return 0;
+		return ( battle_get_adelay(bl) / 2 );
+
 
 	if(bl->type == BL_PC) {
 		if( battle_config.delay_dependon_dex )	/* dexの影響を計算する */
@@ -7629,7 +7619,7 @@ int skill_use_id( struct map_session_data *sd, int target_id,
 	range = skill_get_range(skill_num,skill_lv);
 	if(range < 0)
 		range = battle_get_range(&sd->bl) - (range + 1);
-	if(!battle_check_range(&sd->bl,bl,range) )
+	if(!battle_check_range(&sd->bl,bl,range + 1) )
 		return 0;
 
 	if(bl->type==BL_PC) {
@@ -7721,6 +7711,9 @@ int skill_use_id( struct map_session_data *sd, int target_id,
 	case PF_MEMORIZE:				/* メモライズ */
 		casttime = 12000;
 		break;
+	case HW_MAGICPOWER:
+		casttime = 700;
+		break;
 	case GD_BATTLEORDER:
 	case GD_REGENERATION:
 	case GD_RESTORE:
@@ -7736,11 +7729,6 @@ int skill_use_id( struct map_session_data *sd, int target_id,
 			skill_status_change_end(&sd->bl, SC_MEMORIZE, -1);
 	}
 
-	// instant cast attack skills depend on aspd as delay [celest]
-	if (casttime == 0 && delay == 0 && skill_db[skill_num].skill_type == BF_WEAPON) {
-		delay = battle_get_adelay (&sd->bl) * battle_config.delay_rate / 100;
-	}
-
 	if(battle_config.pc_skill_log)
 		printf("PC %d skill use target_id=%d skill=%d lv=%d cast=%d\n",sd->bl.id,target_id,skill_num,skill_lv,casttime);
 
@@ -7787,10 +7775,6 @@ int skill_use_id( struct map_session_data *sd, int target_id,
 		skill_castend_id(sd->skilltimer,tick,sd->bl.id,0);
 	}
 
-	//マジックパワ?の?果終了
-	//if(sc_data && sc_data[SC_MAGICPOWER].timer != -1 && skill_num != HW_MAGICPOWER)
-	//	skill_status_change_end(&sd->bl,SC_MAGICPOWER,-1);	// moved
-
 	return 0;
 }
 
@@ -7877,6 +7861,9 @@ int skill_use_pos( struct map_session_data *sd,
 	range = skill_get_range(skill_num,skill_lv);
 	if(range < 0)
 		range = battle_get_range(&sd->bl) - (range + 1);
+// be lenient if the skill was cast before we have moved to the correct position [Celest]
+	if (sd->walktimer != -1)
+		range += battle_config.skill_range_leniency;
 	if(!battle_check_range(&sd->bl,&bl,range) )
 		return 0;
 
@@ -8693,6 +8680,7 @@ int skill_status_change_end(struct block_list* bl, int type, int tid)
 			case SC_MARIONETTE:
 			case SC_MARIONETTE2:
 			case SC_SLOWDOWN:
+			case SC_SPEEDUP0:
 /*			case SC_LEADERSHIP:
 			case SC_GLORYWOUNDS:
 			case SC_SOULCOLD:
@@ -8980,23 +8968,10 @@ int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
 	break;
 
 	case SC_SIGHT:	/* サイト */
-		{
-			const int range=7;
-			map_foreachinarea( skill_status_change_timer_sub,
-				bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
-				bl,type,tick);
-
-			if( (--sc_data[type].val2)>0 ){
-				sc_data[type].timer=add_timer(	/* タイマ?再設定 */
-					250+tick, skill_status_change_timer,
-					bl->id, data);
-				return 0;
-			}
-		}
-		break;
 	case SC_RUWACH:	/* ルアフ */
 		{
-			const int range=5;
+			int range = 5;
+			if ( type == SC_SIGHT ) range = 7;
 			map_foreachinarea( skill_status_change_timer_sub,
 				bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,0,
 				bl,type,tick);
@@ -9215,6 +9190,7 @@ int skill_status_change_timer(int tid, unsigned int tick, int id, int data)
 	case SC_MEMORIZE:	/* メモライズ */
 	case SC_BROKNWEAPON:
 	case SC_BROKNARMOR:
+	case SC_SACRIFICE:
 //		if(sc_data[type].timer==tid)
 			sc_data[type].timer=add_timer( 1000*600+tick,skill_status_change_timer, bl->id, data );
 		return 0;
@@ -9679,6 +9655,13 @@ int skill_status_change_start(struct block_list *bl, int type, int val1, int val
 			if(sc_data[SC_CARTBOOST].timer!=-1 )	/* カ?トブ?スト */
 				skill_status_change_end(bl,SC_CARTBOOST,-1);
 			break;
+		case SC_MAGICPOWER:
+			calc_flag = 1;
+			val2 = 1;
+			break;
+		case SC_SACRIFICE:
+			val2 = 5;
+			break;
 		case SC_FLAMELAUNCHER:		/* フレ?ムランチャ? */
 			skill_encchant_eremental_end(bl,SC_FLAMELAUNCHER);
 			break;
@@ -9919,9 +9902,29 @@ int skill_status_change_start(struct block_list *bl, int type, int val1, int val
 			}
 			break;
 
-		/* option2 */
-		case SC_POISON:				/* 毒 */
+			/* option2 */
 		case SC_DPOISON:			/* 猛毒 */
+		{
+			int mhp = battle_get_max_hp(bl);
+			int hp = battle_get_hp(bl);
+			// MHP?1/4????????
+			if (hp > mhp>>2) {
+				if(bl->type == BL_PC) {
+					int diff = mhp*10/100;
+					if (hp - diff < mhp>>2)
+						hp = hp - (mhp>>2);
+					pc_heal((struct map_session_data *)bl, -hp, 0);
+				} else if(bl->type == BL_MOB) {
+					struct mob_data *md = (struct mob_data *)bl;
+					hp -= mhp*15/100;
+					if (hp > mhp>>2)
+						md->hp = hp;
+					else
+						md->hp = mhp>>2;
+				}
+			}
+		}	// fall through
+		case SC_POISON:				/* 毒 */
 			calc_flag = 1;
 			if(!(flag&2)) {
 				int sc_def = 100 - (battle_get_vit(bl) + battle_get_luk(bl)/5);
@@ -10127,7 +10130,6 @@ int skill_status_change_start(struct block_list *bl, int type, int val1, int val
 		case SC_CARTBOOST:		/* カ?トブ?スト */
 		case SC_TRUESIGHT:		/* トゥル?サイト */
 		case SC_SPIDERWEB:		/* スパイダ?ウェッブ */
-		case SC_MAGICPOWER:		/* 魔法力?幅 */
 			calc_flag = 1;
 			break;
 
@@ -10161,6 +10163,7 @@ int skill_status_change_start(struct block_list *bl, int type, int val1, int val
 			break;
 
 		case SC_SLOWDOWN:
+		case SC_SPEEDUP0:
 			calc_flag = 1;
 			break;
 
@@ -12049,7 +12052,8 @@ void skill_reload(void)
 int do_init_skill(void)
 {
 	skill_readdb();
-	skill_read_skillspamount();
+	if (battle_config.skill_sp_override_grffile)
+		skill_read_skillspamount();
 
 	add_timer_func_list(skill_unit_timer,"skill_unit_timer");
 	add_timer_func_list(skill_castend_id,"skill_castend_id");

+ 10 - 9
src/map/skill.h

@@ -313,10 +313,9 @@ enum {	// struct map_session_data 
 
 	SC_SPIDERWEB		=180,		/* スパイダ?ウェッブ */
 	SC_MEMORIZE			=181,		/* メモライズ */
-//	SC_DPOISON			=182,		/* 猛毒 */
-
-//	SC_EDP				=183,		/* エフェクトが判明したら移動 */
-
+	SC_DPOISON			=182,		/* 猛毒 */
+	SC_EDP				=183,		/* エフェクトが判明したら移動 */
+	SC_SACRIFICE		=184,		/* サクリファイス */
 	SC_WEDDING			=187,	//結婚用(結婚衣裳になって?くのが?いとか)
 	SC_NOCHAT			=188,	//赤エモ?態
 	SC_SPLASHER			=189,	/* ベナムスプラッシャ? */
@@ -326,25 +325,27 @@ enum {	// struct map_session_data 
 // Used by English Team
 	SC_BROKNARMOR		=32,
 	SC_BROKNWEAPON		=33,
+	SC_SPEEDUP0			=41, // for skill speedup
+	SC_SPEEDUP1			=42, // for skill speedup
 	SC_SLOWDOWN			=45, // for skill slowdown
 	SC_AUTOBERSERK		=46,
 	SC_SIGHTTRASHER		=73,
 //	SC_BASILICA			=125, // 125 is the same id as joint break
 	SC_BASILICA			=102, // temporarily use this before an actual id is found [celest]
-	SC_EDP				=114, // 
+//	SC_EDP				=114, // 
 	SC_MARIONETTE2		=122, // Marionette target
 	SC_ENSEMBLE			=159,
 	SC_FOGWALL			=178,
 	SC_GOSPEL			=179,
-	SC_LANDPROTECTOR	=182,
-	SC_ADAPTATION		=183,
-	SC_CHASEWALK		=184,
 	SC_ATKPOT			=185,	// [Valaris]
 	SC_MATKPOT			=186,	// [Valaris]
 	SC_MINDBREAKER		=191,
 	SC_SPELLBREAKER		=192,
-	SC_DPOISON			=193, /* 猛毒 */
+	SC_LANDPROTECTOR	=193,
+//	SC_DPOISON			=193, /* 猛毒 */
 	SC_BLOCKSKILL		=194, // for disallowing the use of a skill for a time period
+	SC_ADAPTATION		=195,
+	SC_CHASEWALK		=196,
 /*	SC_LEADERSHIP		=196, // temporarily disabled - they're too buggy =/
 	SC_GLORYWOUNDS		=197,
 	SC_SOULCOLD			=198,