소스 검색

* Fixed a typo in quests/all_quest.txt
* Set 'killerrid' and do PCKillEvent before calling PCDieEvent
* Added some new script event related options to script config
* Added 10 of the new card effects on the 2/15's patch
* Minor rewrites on self and enemy weapon/armor breaking
* Added missing code for 'bBreakWeaponRate' and 'bBreakWeaponRate' effects
* Added missing code for 'bAddStealRate' effect
* Removed redundant 'infinite_autospell' in map_session_data

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

celest 20 년 전
부모
커밋
899b3ebeeb
14개의 변경된 파일409개의 추가작업 그리고 111개의 파일을 삭제
  1. 20 0
      Changelog-SVN.txt
  2. 24 1
      conf-tmpl/script_athena.conf
  3. 3 5
      db/const.txt
  4. 20 0
      doc/item_bonus.txt
  5. 1 0
      npc/Changelog.txt
  6. 1 1
      npc/quests/all_quest.txt
  7. 87 33
      src/map/battle.c
  8. 3 2
      src/map/map.c
  9. 7 5
      src/map/map.h
  10. 99 18
      src/map/pc.c
  11. 39 4
      src/map/script.c
  12. 7 0
      src/map/script.h
  13. 74 42
      src/map/skill.c
  14. 24 0
      src/map/status.c

+ 20 - 0
Changelog-SVN.txt

@@ -1,6 +1,25 @@
 Date	Added
 
 02/16
+        * Set 'killerrid' and do PCKillEvent before calling PCDieEvent, thanks to
+          mrmagoo for pointing it out [celest]
+
+        * Added some new script event related options to script config [celest]
+
+          - [die/kill/login/logout]_event_name: Name of script to activate when an
+                     event has occured
+          - event_requires_trigger: whether or not a 'set [EventName],1;' has to be
+                     defined first for the event to be activated
+
+        * Added 10 of the new card effects on the 2/15's patch (still untested and
+          not yet added to the item_db)
+          - Refer to doc/item_bonus.txt for description
+
+        * Minor rewrites on self and enemy weapon/armor breaking during battle [celest]
+        * Added missing code for 'bBreakWeaponRate' and 'bBreakWeaponRate' effects
+          [celest]
+        * Added missing code for 'bAddStealRate' effect [celest]
+        * Removed redundant 'infinite_autospell' in map_session_data [celest]
         * Fixed Treasure Box spawn bug in all castles. [Lupus]
         * Fixed wrong PresentLOG (it wasn't showing PRESENT BOX type ID) [Lupus]
 	* Expanded Monsters Drops Slots from 8 to 10. Everywhere in the sources. [Lupus]
@@ -10,6 +29,7 @@ Date	Added
 	  On expanding MOB_DB.TXT we'll remove that plug.
 	  We are adding new cards and some monsters
 	  have no free slots for them. Current state is tested and works fine.
+
 02/15
         * Allow Potion Pitcher to be able to cast on yourself -- i've almost forgot
           about this, thanks to Filougarou and Poki#3 for the fix ^^; [celest]

+ 24 - 1
conf-tmpl/script_athena.conf

@@ -11,4 +11,27 @@ warn_cmd_mismatch_paramnum: yes
 
 check_cmdcount: 8192
 
-check_gotocount: 512
+check_gotocount: 512
+
+
+//---- Custom script functions ----
+
+// 0 - Event script is defined as an NPC by itself
+// 1 - Event script can be called by script label
+event_script_type: 0
+
+// Name of event when a player has died
+die_event_name: PCDieEvent
+
+// Name of event when a player kills something
+kill_event_name: PCKillEvent
+
+// Name of event when a player logs out
+logout_event_name: PCLogoutEvent
+
+// Name of event when a player logs in
+login_event_name: PCLoginEvent
+
+// For events to be activated do we require
+// a 'set [EventName],1;' to be called first?
+event_requires_trigger: yes

+ 3 - 5
db/const.txt

@@ -110,8 +110,8 @@ MaxHp		6	1
 Sp		7	1
 MaxSp		8	1
 BaseJob		119	1
-Karma		4
-Manner		5
+Karma		4	1
+Manner		5	1
 
 bMaxHP		6
 bMaxSP		8
@@ -241,9 +241,7 @@ bAddEffWhenHit	2016
 bAutoSpellWhenHit	2017
 bSkillAtk	2018
 bUnstripable	2019
-bAddMob	2020
-bSubMob	2021
-bAddByMob	2022
+bAddDamageByClass	2020
 
 
 Eff_Stone	0

+ 20 - 0
doc/item_bonus.txt

@@ -135,3 +135,23 @@ bonus3 bAutoSpell,n,x,y;		Auto Spell casting of spell n at level x with y% chanc
 
 // bAddDamageClass, bAddMagicDamageClass and bAddMonsterDropItem it is setting possible up to 10. Those which exceed 10 are ignored.
 // those which can be used with the arrow are only bCritical, bAtkEle, bHit, bAddEle, bAddRace, bAddSize and bAddEff. The other things are ignored.
+
+
+
+//---- 2/15 new card effects ----
+
+bonus bCritAtkRate,n;			Increase critical damage by +n%
+bonus bNoRegen,n;			Stops regeneration for n.
+                                        n: 1=HP, 2=SP
+bonus bUnstripable,n;			Armor cannot be taken off via Strip skills
+
+bonus2 bCriticalAddRace,n,x;		Increase critical + n vs. enemies of type x
+
+bonus2 bAddEffWhenHit,n,x;		n% chance to cause x state to the enemy when
+                                        being hit by physical close range damage
+bonus2 bSkillAtk,n,x;			Increase damage of skill n by x%
+bonus2 bAddDamageByClass,n,x;		When being hit by monster of class n increase
+                                        damage taken by x%
+
+bonus3 bAutoSpellWhenHit,x,y,n;		n% chance to cast skill x of level y when
+                                        being hit by physical close range damage

+ 1 - 0
npc/Changelog.txt

@@ -35,6 +35,7 @@ Other Ppl
 Date		Added
 ======
 02/16
+        * Fixed a typo in quests/all_quest.txt, thanks to hongmei [celest]
         * Fixed treasure chests spawn in the castles. (had to simplify some code and unroll some loops) [Lupus]
 
 02/13

+ 1 - 1
npc/quests/all_quest.txt

@@ -501,7 +501,7 @@ LCancel6:
 Headset:
 	mes "[Quest Assistant]";
 	mes "These are Articles needed for my Grandfather's masterpiece.";
-	mes "^3355FF100 Steel^000000";
+	mes "^3355FF40 Steel^000000";
 	mes "^3355FF1 Oridecon^000000";
 	mes "^3355FF1 Alchol^000000";
 	mes "^3355FF1 Coal^000000";

+ 87 - 33
src/map/battle.c

@@ -1508,6 +1508,12 @@ static struct Damage battle_calc_mob_weapon_attack(
 				break;
 			}
 		}
+		for(i=0;i<tsd->add_damage_class_count2;i++) {
+			if(tsd->add_damage_classid2[i] == md->class_) {
+				cardfix=cardfix*(100+tsd->add_damage_classrate2[i])/100;
+				break;
+			}
+		}
 		if(flag&BF_LONG)
 			cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
 		if(flag&BF_SHORT)
@@ -1776,6 +1782,7 @@ static struct Damage battle_calc_pc_weapon_attack(
 	if(da == 0){ //ダブルアタックが発動していない
 		// クリティカル計算
 		cri = status_get_critical(src);
+		cri += sd->critaddrace[t_race];
 
 		if(sd->state.arrow_atk)
 			cri += sd->arrow_cri;
@@ -1798,7 +1805,6 @@ static struct Damage battle_calc_pc_weapon_attack(
 			else
 				cri <<= 1;
 		}
-
 		if(skill_num == SN_SHARPSHOOTING)
 			cri += 200;
 	}
@@ -1812,13 +1818,16 @@ static struct Damage battle_calc_pc_weapon_attack(
 		damage += atkmax;
 		damage2 += atkmax_;
 		if(sd->atk_rate != 100 || sd->weapon_atk_rate != 0) {
-                    if (sd->status.weapon < 16) {
-			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->status.weapon < 16) {
+				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;
+
+		damage += damage * sd->crit_atk_rate / 100;
+		
 		type = 0x0a;
 
 /*		if(def1 < 1000000) {
@@ -2322,6 +2331,8 @@ static struct Damage battle_calc_pc_weapon_attack(
 				damage *= div_;
 				damage2 *= div_;
 			}
+			if (sd && skill_num > 0 && sd->skillatk[0] == skill_num)
+				damage += damage*sd->skillatk[1]/100;
 		}
 		if(da == 2) { //三段掌が発動しているか
 			type = 0x08;
@@ -2815,37 +2826,45 @@ struct Damage battle_calc_weapon_attack(
 		memset(&wd,0,sizeof(wd));
 
 	if(battle_config.equipment_breaking && src->type==BL_PC && (wd.damage > 0 || wd.damage2 > 0)) {
-		struct map_session_data *sd=(struct map_session_data *)src;
-		int breakrate = 1;	//0.01% weapon breaking chance [DracoRPG]
-
-		if(sd->status.weapon && sd->status.weapon != 11) {
-			if(sd->sc_data[SC_MELTDOWN].timer!=-1) {
-				int breakrate_;	// separate breaking rates for meltdown [Celest]
-				breakrate_ = 100*sd->sc_data[SC_MELTDOWN].val1;
-				if(rand()%10000 < breakrate_*battle_config.equipment_break_rate/100 || breakrate_ >= 10000) {
-					if (target->type == BL_PC)
-						pc_breakweapon((struct map_session_data *)target);
-					else
-						status_change_start(target,SC_STRIPWEAPON,1,75,0,0,skill_get_time2(WS_MELTDOWN,1),0 );
-				}
-
-				breakrate_ = 70*sd->sc_data[SC_MELTDOWN].val1;
-				if (rand()%10000 < breakrate_*battle_config.equipment_break_rate/100 || breakrate_ >= 10000) {
-					if (target->type == BL_PC)
-						pc_breakarmor((struct map_session_data *)target);
-					else
-						status_change_start(target,SC_STRIPSHIELD,1,75,0,0,skill_get_time2(WS_MELTDOWN,1),0 );
-				}
+		struct map_session_data *sd = (struct map_session_data *)src;
+		// weapon = 0, armor = 1
+		int breakrate = 1;	//0.01% default self weapon breaking chance [DracoRPG]
+		int breakrate_[2] = {0,0};	//enemy breaking chance [celest]
+		int breaktime = 5000;
+
+		breakrate_[0] += sd->break_weapon_rate;
+		breakrate_[1] += sd->break_armor_rate;
+		
+		if (sd->sc_count) {
+			if (sd->sc_data[SC_MELTDOWN].timer!=-1) {
+				breakrate_[0] += 100*sd->sc_data[SC_MELTDOWN].val1;
+				breakrate_[1] = 70*sd->sc_data[SC_MELTDOWN].val1;
+				breaktime = skill_get_time2(WS_MELTDOWN,1);
 			}
 			if(sd->sc_data[SC_OVERTHRUST].timer!=-1)
-				breakrate += 10;	//+ 0.1% whatever skill level you use [DracoRPG]
+				breakrate += 10;
+		}
 
-			//if(wd.type==0x0a) //removed! because CRITS don't affect on breaking chance [Lupus]
-			//	breakrate*=2;
-			if(rand()%10000 < breakrate*battle_config.equipment_break_rate/100 || breakrate >= 10000) {
-				if(pc_breakweapon(sd)==1)
+		if(sd->status.weapon && sd->status.weapon != 11) {
+			if(rand() % 10000 < breakrate * battle_config.equipment_break_rate / 100 || breakrate >= 10000)
+				if (pc_breakweapon(sd) == 1)
 					wd = battle_calc_pc_weapon_attack(src,target,skill_num,skill_lv,wflag);
-			}
+		}
+		if(rand() % 10000 < breakrate_[0] * battle_config.equipment_break_rate / 100 || breakrate_[0] >= 10000) {
+			if (target->type == BL_PC) {
+				struct map_session_data *tsd = (struct map_session_data *)target;
+				if(tsd->status.weapon != 11)
+					pc_breakweapon(tsd);
+			} else
+				status_change_start(target,SC_STRIPWEAPON,1,75,0,0,breaktime,0);
+		}
+		if(rand() % 10000 < breakrate_[1] * battle_config.equipment_break_rate/100 || breakrate_[1] >= 10000) {
+			if (target->type == BL_PC) {
+				struct map_session_data *tsd = (struct map_session_data *)target;
+				if(tsd->status.weapon != 11)
+					pc_breakarmor(tsd);
+			} else
+				status_change_start(target,SC_STRIPSHIELD,1,75,0,0,breaktime,0);
 		}
 	}
 
@@ -3084,6 +3103,8 @@ struct Damage battle_calc_magic_attack(
 			}
 		}
 		damage=damage*cardfix/100;
+		if (skill_num > 0 && sd->skillatk[0] == skill_num)
+			damage += damage*sd->skillatk[1]/100;
 	}
 
 	if( tsd ){
@@ -3283,6 +3304,9 @@ struct Damage  battle_calc_misc_attack(
 			cardfix=cardfix*(100-tsd->misc_def_rate)/100;
 			damage=damage*cardfix/100;
 		}
+		if (sd && skill_num > 0 && sd->skillatk[0] == skill_num)
+			damage += damage*sd->skillatk[1]/100;
+
 		if(damage < 0) damage = 0;
 		damage=battle_attr_fix(damage, ele, status_get_element(target) );		// 属性修正
 	}
@@ -3517,7 +3541,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 			}
 		}
 		if(sd) {
-			if(sd->autospell_id > 0 && sd->autospell_lv > 0 && rand()%100 < sd->autospell_rate) {
+			if(sd->autospell_id > 0 && rand()%100 < sd->autospell_rate) {
 				int skilllv=sd->autospell_lv,i,f=0,sp;
 				i = rand()%100;
 				if(i >= 50) skilllv -= 2;
@@ -3564,6 +3588,36 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 				if (hp || sp) pc_heal(sd, hp, sp);
 			}
 		}
+		if (target->type == BL_PC) {
+			struct map_session_data *tsd = (struct map_session_data *)target;
+			if(tsd->autospell2_id > 0 && rand()%100 < tsd->autospell2_rate) {
+				int skilllv = tsd->autospell_lv,i,f=0,sp;
+				i = rand()%100;
+				if(i >= 50) skilllv -= 2;
+				else if(i >= 15) skilllv--;
+				if(skilllv < 1) skilllv = 1;
+				sp = skill_get_sp(tsd->autospell2_id,skilllv)*2/3;
+				if(tsd->status.sp >= sp) {
+					if((i=skill_get_inf(tsd->autospell2_id) == 2) || i == 32)
+						f = skill_castend_pos2(target,src->x,src->y,tsd->autospell2_id,skilllv,tick,flag);
+					else {
+						switch( skill_get_nk(tsd->autospell2_id) ) {
+							case 0:	case 2:
+								f = skill_castend_damage_id(target,src,tsd->autospell2_id,skilllv,tick,flag);
+								break;
+							case 1:/* 支援系 */
+								if((tsd->autospell2_id==AL_HEAL || (tsd->autospell2_id==ALL_RESURRECTION && src->type != BL_PC)) &&
+									battle_check_undead(status_get_race(src),status_get_elem_type(src)))
+									f = skill_castend_damage_id(target,src,tsd->autospell2_id,skilllv,tick,flag);
+								else
+									f = skill_castend_nodamage_id(target,src,tsd->autospell2_id,skilllv,tick,flag);
+								break;
+						}
+					}
+					if(!f) pc_heal(tsd,0,-sp);
+				}
+			}
+		}
 
 		if(rdamage > 0)
 			battle_damage(target,src,rdamage,0);

+ 3 - 2
src/map/map.c

@@ -1426,9 +1426,10 @@ int map_quit(struct map_session_data *sd) {
 
 	if (sd->state.event_disconnect) {
 		struct npc_data *npc;
-		if ((npc = npc_name2id("PCLogoutEvent"))) {
+		if ((npc = npc_name2id(script_config.logout_event_name))) {
 			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
-			ShowStatus("Event '"CL_WHITE"PCLogoutEvent"CL_RESET"' executed.\n");
+			sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
+			ShowStatus(tmp_output);
 		}
 	}
 

+ 7 - 5
src/map/map.h

@@ -275,15 +275,17 @@ struct map_session_data {
 	int weapon_coma_ele[10],weapon_coma_race[12];
 	int break_weapon_rate,break_armor_rate;
 	short add_steal_rate;
-	//--- 02/15's new card effectds [celest]
+	//--- 02/15's new card effects [celest]
 	int crit_atk_rate;
-	int critaddrace[12],critaddrace_[12],arrow_critaddrace[12];
+	int critaddrace[12];
 	int no_regen;
-	int addeff3[10], arrow_addeff3[10];
+	int addeff3[10];
 	short autospell2_id,autospell2_lv,autospell2_rate;
 	int skillatk[2];
 	unsigned short unstripable_equip;
-	int addmob[2],submob[2],addbymob[2];
+	short add_damage_classid2[10];
+	int add_damage_classrate2[10];
+	int add_damage_class_count2;
 
 	short spiritball, spiritball_old;
 	int spirit_timer[MAX_SKILL_LEVEL];
@@ -625,7 +627,7 @@ enum {
 
 	SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
 	SP_SKILL_ATK, SP_UNSTRIPABLE, // 2018-2019
-	SP_ADDMOB, SP_SUBMOB, SP_ADDBYMOB // 2020-2022
+	SP_ADD_DAMAGE_BY_CLASS // 2020-2022
 };
 
 enum {

+ 99 - 18
src/map/pc.c

@@ -808,9 +808,16 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
 	sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
 
 	// Automated script events
-	sd->state.event_death = pc_readglobalreg(sd,"PCDieEvent");
-	sd->state.event_kill = pc_readglobalreg(sd,"PCKillEvent");
-	sd->state.event_disconnect = pc_readglobalreg(sd,"PCLogoffEvent");
+	if (script_config.event_requires_trigger) {
+		sd->state.event_death = pc_readglobalreg(sd,"PCDieEvent");
+		sd->state.event_kill = pc_readglobalreg(sd,"PCKillEvent");
+		sd->state.event_disconnect = pc_readglobalreg(sd,"PCLogoffEvent");
+	// if script triggers are not required
+	} else {
+		sd->state.event_death = 1;
+		sd->state.event_kill = 1;
+		sd->state.event_disconnect = 1;
+	}
 
 	if (night_flag == 1 && !map[sd->bl.m].flag.indoors) {
 		char tmpstr[1024];
@@ -835,9 +842,10 @@ int pc_authok(int id, int login_id2, time_t connect_until_time, struct mmo_chars
 	{
 		struct npc_data *npc;
 		//printf("pc: OnPCLogin event done. (%d events)\n", npc_event_doall("OnPCLogin") );
-		if ((npc = npc_name2id("PCLoginEvent"))) {
+		if ((npc = npc_name2id(script_config.login_event_name))) {
 			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLoginNPC
-			ShowStatus("Event '"CL_WHITE"PCLoginEvent"CL_RESET"' executed.\n");
+			sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.login_event_name);
+			ShowStatus(tmp_output);
 		}
 	}
 	// Send friends list
@@ -1539,10 +1547,34 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		if(sd->status.weapon == 11 && sd->state.lr_flag != 2)
 			sd->atk_rate += val;
 		break;
+	case SP_BREAK_WEAPON_RATE:
+		if(sd->state.lr_flag != 2)
+			sd->break_weapon_rate+=val;
+		break;
+	case SP_BREAK_ARMOR_RATE:
+		if(sd->state.lr_flag != 2)
+			sd->break_armor_rate+=val;
+		break;
+	case SP_ADD_STEAL_RATE:
+		if(sd->state.lr_flag != 2)
+			sd->add_steal_rate+=val;
+		break;
 	case SP_DELAYRATE:
 		if(sd->state.lr_flag != 2)
 			sd->delayrate+=val;
 		break;
+	case SP_CRIT_ATK_RATE:
+		if(sd->state.lr_flag != 2)
+			sd->crit_atk_rate += val;
+		break;
+	case SP_NO_REGEN:
+		if(sd->state.lr_flag != 2)
+			sd->no_regen = val;
+		break;
+	case SP_UNSTRIPABLE:
+		if(sd->state.lr_flag != 2)
+			sd->unstripable_equip |= EQP_ARMOR;
+		break;
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus: unknown type %d %d !\n",type,val);
@@ -1758,6 +1790,39 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 		if(sd->state.lr_flag != 2)
 			sd->weapon_atk_rate[type2]+=val;
 		break;
+	case SP_CRITICAL_ADDRACE:
+		if(sd->state.lr_flag != 2)
+			sd->critaddrace[type2]+=val;
+		break;
+	case SP_ADDEFF_WHENHIT:
+		if(sd->state.lr_flag != 2)
+			sd->addeff3[type2]+=val;
+		break;
+	case SP_SKILL_ATK:
+		if(sd->state.lr_flag != 2) {
+			if (sd->skillatk[0] == type2)
+				sd->skillatk[1] += val;
+			else {
+				sd->skillatk[0] = type2;
+				sd->skillatk[1] = val;
+			}
+		}
+		break;
+	case SP_ADD_DAMAGE_BY_CLASS:
+		if(sd->state.lr_flag != 2) {
+			for(i=0;i<sd->add_damage_class_count2;i++) {
+				if(sd->add_damage_classid2[i] == type2) {
+					sd->add_damage_classrate2[i] += val;
+					break;
+				}
+			}
+			if(i >= sd->add_damage_class_count2 && sd->add_damage_class_count2 < 10) {
+				sd->add_damage_classid2[sd->add_damage_class_count2] = type2;
+				sd->add_damage_classrate2[sd->add_damage_class_count2] += val;
+				sd->add_damage_class_count2++;				
+			}			
+		}
+		break;
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
@@ -1795,6 +1860,13 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 			sd->autospell_rate = val;
 		}
 		break;
+	case SP_AUTOSPELL_WHENHIT:
+		if(sd->state.lr_flag != 2){
+			sd->autospell2_id = type2;
+			sd->autospell2_lv = type3;
+			sd->autospell2_rate = val;
+		}
+		break;
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
@@ -2622,6 +2694,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl)
 					if(itemid > 0 && itemdb_type(itemid) != 6)
 					{
 						rate = (mob_db[md->class_].dropitem[i].p / battle_config.item_rate_common * 100 * skill)/100;
+						rate += sd->add_steal_rate;
 
 						if(rand()%10000 < rate)
 						{
@@ -4467,25 +4540,27 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage)
 	clif_updatestatus(sd,SP_HP);
 	status_calc_pc(sd,0);
 
-	if (sd->state.event_death) {
-		struct npc_data *npc;
-		if ((npc = npc_name2id("PCDeathEvent"))) {
-			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC
-			ShowStatus("Event '"CL_WHITE"PCDeathEvent"CL_RESET"' executed.\n");
-		}
-	}
-
 	if (src && src->type == BL_PC) {
+		if (sd->state.event_death)
+			pc_setglobalreg(sd,"killerrid",((struct map_session_data *)src)->status.account_id);
+
 		if (((struct map_session_data *)src)->state.event_kill) {
 			struct npc_data *npc;
-			if ((npc = npc_name2id("PCKillEvent"))) {
+			if ((npc = npc_name2id(script_config.kill_event_name))) {
 				run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCKillNPC
-				ShowStatus("Event '"CL_WHITE"PCKillEvent"CL_RESET"' executed.\n");
+				sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.kill_event_name);
+				ShowStatus(tmp_output);
 			}
-		}
+		}	
+	}
 
-		if (sd->state.event_death)
-			pc_setglobalreg(sd,"killerrid",((struct map_session_data *)src)->status.account_id);
+	if (sd->state.event_death) {
+		struct npc_data *npc;
+		if ((npc = npc_name2id(script_config.die_event_name))) {
+			run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCDeathNPC
+			sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.die_event_name);
+			ShowStatus(tmp_output);
+		}
 	}
 
 	if(battle_config.bone_drop==2
@@ -6277,6 +6352,9 @@ static int pc_natural_heal_hp(struct map_session_data *sd)
 	if (sd->sc_count && sd->sc_data[SC_TRICKDEAD].timer != -1)		// Modified by RoVeRT
 		return 0;
 
+	if (sd->no_regen & 1)
+		return 0;
+
 	if(pc_checkoverhp(sd)) {
 		sd->hp_sub = sd->inchealhptick = 0;
 		return 0;
@@ -6376,6 +6454,9 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
 		sd->sc_data[SC_BERSERK].timer != -1))
 		return 0;
 
+	if (sd->no_regen & 2)
+		return 0;
+
 	if(pc_checkoversp(sd)) {
 		sd->sp_sub = sd->inchealsptick = 0;
 		return 0;

+ 39 - 4
src/map/script.c

@@ -7222,6 +7222,14 @@ int script_config_read(char *cfgName)
 	script_config.check_cmdcount=8192;
 	script_config.check_gotocount=512;
 
+	script_config.die_event_name = (char *)aCallocA(24,sizeof(char));
+	script_config.kill_event_name = (char *)aCallocA(24,sizeof(char));
+	script_config.login_event_name = (char *)aCallocA(24,sizeof(char));
+	script_config.logout_event_name = (char *)aCallocA(24,sizeof(char));
+
+	script_config.event_script_type = 0;
+	script_config.event_requires_trigger = 1;
+
 	fp=fopen(cfgName,"r");
 	if(fp==NULL){
 		printf("file not found: %s\n",cfgName);
@@ -7254,6 +7262,24 @@ int script_config_read(char *cfgName)
 		else if(strcmpi(w1,"check_gotocount")==0) {
 			script_config.check_gotocount = battle_config_switch(w2);
 		}
+		else if(strcmpi(w1,"event_script_type")==0) {
+			script_config.event_script_type = battle_config_switch(w2);
+		}
+		else if(strcmpi(w1,"die_event_name")==0) {			
+			strcpy(script_config.die_event_name, w2);			
+		}
+		else if(strcmpi(w1,"kill_event_name")==0) {
+			strcpy(script_config.kill_event_name, w2);
+		}
+		else if(strcmpi(w1,"login_event_name")==0) {
+			strcpy(script_config.login_event_name, w2);
+		}
+		else if(strcmpi(w1,"logout_event_name")==0) {
+			strcpy(script_config.logout_event_name, w2);
+		}
+		else if(strcmpi(w1,"require_set_trigger")==0) {
+			script_config.event_requires_trigger = battle_config_switch(w2);
+		}
 		else if(strcmpi(w1,"import")==0){
 			script_config_read(w2);
 		}
@@ -7302,10 +7328,19 @@ int do_final_script()
 	if(userfunc_db)
 		strdb_final(userfunc_db,userfunc_db_final);
 
-        if (str_data)
-            aFree(str_data);
-        if (str_buf)
-            aFree(str_buf);
+	if (str_data)
+		aFree(str_data);
+	if (str_buf)
+		aFree(str_buf);
+
+	if (script_config.die_event_name)
+		aFree(script_config.die_event_name);
+	if (script_config.kill_event_name)
+		aFree(script_config.die_event_name);
+	if (script_config.login_event_name)
+		aFree(script_config.die_event_name);
+	if (script_config.logout_event_name)
+		aFree(script_config.die_event_name);
 
 	return 0;
 }

+ 7 - 0
src/map/script.h

@@ -9,6 +9,13 @@ extern struct Script_Config {
 	int warn_cmd_mismatch_paramnum;
 	int check_cmdcount;
 	int check_gotocount;
+
+	int event_script_type;
+	char* die_event_name;
+	char* kill_event_name;
+	char* login_event_name;
+	char* logout_event_name;
+	int event_requires_trigger;
 } script_config;
 
 struct script_data {

+ 74 - 42
src/map/skill.c

@@ -1050,7 +1050,7 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
 					diff = mhp*10/100;
 					if (hp - diff < mhp>>2)
 						diff = hp - (mhp>>2);
-					pc_heal((struct map_session_data *)bl, -hp, 0);
+					pc_heal(dstsd, -hp, 0);
 				} else if(bl->type == BL_MOB) {
 					struct mob_data *md = (struct mob_data *)bl;
 					hp -= mhp*15/100;
@@ -1287,59 +1287,89 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl,int s
 		break;
 	}
 
-	if(sd && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){	/* カ?ドによる追加?果 */
+	if((sd||dstsd) && skillid != MC_CARTREVOLUTION && attack_type&BF_WEAPON){	/* カ?ドによる追加?果 */
 		int i;
 		int sc_def_card=100;
 
 		for(i=SC_STONE;i<=SC_BLIND;i++){
 			//?象に?態異常
-			if(i==SC_STONE || i==SC_FREEZE)
-				sc_def_card=sc_def_mdef;
-			else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
-				sc_def_card=sc_def_vit;
-			else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
-				sc_def_card=sc_def_int;
-			else if(i==SC_CURSE)
-				sc_def_card=sc_def_luk;
-
-			if(!sd->state.arrow_atk) {
-				if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
-					if(battle_config.battle_log)
-						printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
-					status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
-				}
+			switch (i) {
+				case SC_STONE:
+				case SC_FREEZE:
+					sc_def_card=sc_def_mdef;
+					break;
+				case SC_STAN:
+				case SC_POISON:
+				case SC_SILENCE:
+					sc_def_card=sc_def_vit;
+					break;
+				case SC_SLEEP:
+				case SC_CONFUSION:
+				case SC_BLIND:
+					sc_def_card=sc_def_int;
+					break;
+				case SC_CURSE:
+					sc_def_card=sc_def_luk;
 			}
-			else {
-				if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
-					if(battle_config.battle_log)
-						printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
-					status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+			if (sd) {
+				if(!sd->state.arrow_atk) {
+					if(rand()%10000 < (sd->addeff[i-SC_STONE])*sc_def_card/100 ){
+						if(battle_config.battle_log)
+							printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
+						status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+					}
+				}
+				else {
+					if(rand()%10000 < (sd->addeff[i-SC_STONE]+sd->arrow_addeff[i-SC_STONE])*sc_def_card/100 ){
+						if(battle_config.battle_log)
+							printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",sd->bl.id,i,sd->addeff[i-SC_STONE]);
+						status_change_start(bl,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+					}
 				}
 			}
 			//自分に?態異常
-			if(i==SC_STONE || i==SC_FREEZE)
-				sc_def_card=sc_def_mdef2;
-			else if(i==SC_STAN || i==SC_POISON || i==SC_SILENCE)
-				sc_def_card=sc_def_vit2;
-			else if(i==SC_SLEEP || i==SC_CONFUSION || i==SC_BLIND)
-				sc_def_card=sc_def_int2;
-			else if(i==SC_CURSE)
-				sc_def_card=sc_def_luk2;
-
-			if(!sd->state.arrow_atk) {
-				if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
-					if(battle_config.battle_log)
-						printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
-					status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
-				}
+			switch (i) {
+				case SC_STONE:
+				case SC_FREEZE:
+					sc_def_card=sc_def_mdef2;
+					break;
+				case SC_STAN:
+				case SC_POISON:
+				case SC_SILENCE:
+					sc_def_card=sc_def_vit2;
+					break;
+				case SC_SLEEP:
+				case SC_CONFUSION:
+				case SC_BLIND:
+					sc_def_card=sc_def_int2;
+					break;
+				case SC_CURSE:
+					sc_def_card=sc_def_luk2;
 			}
-			else {
-				if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
-					if(battle_config.battle_log)
-						printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
-					status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+
+			if (sd) {
+				if(!sd->state.arrow_atk) {
+					if(rand()%10000 < (sd->addeff2[i-SC_STONE])*sc_def_card/100 ){
+						if(battle_config.battle_log)
+							printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
+						status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+					}
+				}
+				else {
+					if(rand()%10000 < (sd->addeff2[i-SC_STONE]+sd->arrow_addeff2[i-SC_STONE])*sc_def_card/100 ){
+						if(battle_config.battle_log)
+							printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,sd->addeff2[i-SC_STONE]);
+						status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+					}
 				}
 			}
+			if (dstsd &&
+				rand()%10000 < dstsd->addeff3[i-SC_STONE]*sc_def_card/100){
+				if(battle_config.battle_log)
+					printf("PC %d skill_addeff: cardによる異常?動 %d %d\n",src->id,i,dstsd->addeff3[i-SC_STONE]);
+				status_change_start(src,i,7,0,0,0,(i==SC_CONFUSION)? 10000+7000:skill_get_time2(sc2[i-SC_STONE],7),0);
+			}
 		}
 	}
 	return 0;
@@ -3952,6 +3982,8 @@ int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,int
 
 		if (tsc_data && tsc_data[scid].timer != -1)
 			break;
+		if (dstsd && dstsd->unstripable_equip & equip)
+			break;
 
 		strip_fix = status_get_dex(src) - status_get_dex(bl);
 		if(strip_fix < 0)

+ 24 - 0
src/map/status.c

@@ -252,6 +252,30 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	sd->hp_drain_value = sd->hp_drain_value_ = sd->sp_drain_value = sd->sp_drain_value_ = 0;
 	sd->unbreakable_equip = 0;
 
+	sd->break_weapon_rate = sd->break_armor_rate = 0;
+	sd->add_steal_rate = 0;
+	sd->crit_atk_rate = 0;
+	sd->no_regen = 0;
+	sd->unstripable_equip = 0;
+	sd->autospell2_id = sd->autospell2_lv = sd->autospell2_rate = 0;
+	memset(sd->critaddrace,0,sizeof(sd->critaddrace));
+	memset(sd->addeff3,0,sizeof(sd->addeff3));
+	memset(sd->skillatk,0,sizeof(sd->skillatk));
+	sd->add_damage_class_count = sd->add_damage_class_count_ = sd->add_magic_damage_class_count = 0;
+	sd->add_def_class_count = sd->add_mdef_class_count = 0;
+	sd->add_damage_class_count2 = 0;
+	memset(sd->add_damage_classid,0,sizeof(sd->add_damage_classid));
+	memset(sd->add_damage_classid_,0,sizeof(sd->add_damage_classid_));
+	memset(sd->add_magic_damage_classid,0,sizeof(sd->add_magic_damage_classid));
+	memset(sd->add_damage_classrate,0,sizeof(sd->add_damage_classrate));
+	memset(sd->add_damage_classrate_,0,sizeof(sd->add_damage_classrate_));
+	memset(sd->add_magic_damage_classrate,0,sizeof(sd->add_magic_damage_classrate));
+	memset(sd->add_def_classid,0,sizeof(sd->add_def_classid));
+	memset(sd->add_def_classrate,0,sizeof(sd->add_def_classrate));
+	memset(sd->add_mdef_classid,0,sizeof(sd->add_mdef_classid));
+	memset(sd->add_mdef_classrate,0,sizeof(sd->add_mdef_classrate));
+	memset(sd->add_damage_classid2,0,sizeof(sd->add_damage_classid2));
+	memset(sd->add_damage_classrate2,0,sizeof(sd->add_damage_classrate2));
 
 	if(!sd->disguiseflag && sd->disguise) {
 		sd->disguise=0;