Kaynağa Gözat

Added 3 more of the new card effects

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1117 54d463be-8e91-2dee-dedb-b68131a5f0ec
celest 20 yıl önce
ebeveyn
işleme
528ed3e19f
10 değiştirilmiş dosya ile 162 ekleme ve 35 silme
  1. 6 2
      Changelog-SVN.txt
  2. 6 3
      db/const.txt
  3. 6 1
      doc/item_bonus.txt
  4. 22 6
      src/map/battle.c
  5. 9 6
      src/map/map.h
  6. 15 10
      src/map/mob.c
  7. 76 7
      src/map/pc.c
  8. 1 0
      src/map/pc.h
  9. 18 0
      src/map/script.c
  10. 3 0
      src/map/status.c

+ 6 - 2
Changelog-SVN.txt

@@ -1,6 +1,10 @@
 Date	Added
 
 02/16
+        * Added 3 more of the new card effects -- check item_bonus.txt [celest]
+
+        * Added 'bonus4' to support the new card effects that might need up to 4
+          parameters [celest]
         * Set 'killerrid' and do PCKillEvent before calling PCDieEvent, thanks to
           mrmagoo for pointing it out [celest]
 
@@ -11,12 +15,12 @@ Date	Added
           - 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
+        * Added 8 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
+        * Added missing code for 'bBreakWeaponRate' and 'bBreakArmorRate' effects
           [celest]
         * Added missing code for 'bAddStealRate' effect [celest]
         * Removed redundant 'infinite_autospell' in map_session_data [celest]

+ 6 - 3
db/const.txt

@@ -242,6 +242,9 @@ bAutoSpellWhenHit	2017
 bSkillAtk	2018
 bUnstripable	2019
 bAddDamageByClass	2020
+bSPGainValue	2021
+bIgnoreDefMob	2022
+bHPLossRate	2023
 
 
 Eff_Stone	0
@@ -253,6 +256,7 @@ Eff_Curse	5
 Eff_Silence	6
 Eff_Confusion	7
 Eff_Blind	8
+Eff_Bleeding	9
 
 SC_Stone	128
 SC_Freeze	129
@@ -263,6 +267,7 @@ SC_Curse	133
 SC_Silence	134
 SC_Confusion	135
 SC_Blind	136
+SC_Bleeding	137
 SC_SpeedPot0	37
 SC_SpeedPot1	38
 SC_SpeedPot2	39
@@ -275,6 +280,4 @@ SC_Holy		17
 SC_Flame	90
 SC_Frost	91
 SC_Lightning	92
-SC_Seismic	93
-SC_Bleeding	124
-SC_BlockSkill	194
+SC_Seismic	93

+ 6 - 1
doc/item_bonus.txt

@@ -144,9 +144,14 @@ 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
+bonus bSPGainValue,n;			When killing a monster by physical attack
+                                        gain n amount of sp
+bonus bIgnoreDefMob,n;			Ignore monster's DEF when attacking.
+                                        n:0=All normal monsters, except Bosses
+                                          1=All monsters
 
 bonus2 bCriticalAddRace,n,x;		Increase critical + n vs. enemies of type x
-
+bonus2 bHPLossRate,n,x;			Lose n amount of hp every x amount of time
 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%

+ 22 - 6
src/map/battle.c

@@ -2365,6 +2365,19 @@ static struct Damage battle_calc_pc_weapon_attack(
 				}
 				t_def = def2*8/10;
 				vitbonusmax = (t_vit/20)*(t_vit/20)-1;
+				if (tmd) {
+					if(t_mode & 0x20) {
+						if(sd->ignore_def_mob & 2)
+							idef_flag = 1;
+						if(sd->ignore_def_mob_ & 2)
+							idef_flag_ = 1;
+					} else {
+						if(sd->ignore_def_mob & 1)
+							idef_flag = 1;
+						if(sd->ignore_def_mob_ & 1)
+							idef_flag_ = 1;
+					}
+				}
 				if(sd->ignore_def_ele & (1<<t_ele) || sd->ignore_def_race & (1<<t_race))
 					idef_flag = 1;
 				if(sd->ignore_def_ele_ & (1<<t_ele) || sd->ignore_def_race_ & (1<<t_race))
@@ -3598,19 +3611,22 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 				if(skilllv < 1) skilllv = 1;
 				sp = skill_get_sp(tsd->autospell2_id,skilllv)*2/3;
 				if(tsd->status.sp >= sp) {
+					struct block_list *tbl;
+					if (tsd->autospell2_type == 0) tbl = target;
+					else tbl = src;
 					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);
+						f = skill_castend_pos2(target,tbl->x,tbl->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);
+								f = skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
 								break;
 							case 1:/* Žx‰‡Œn */
-								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);
+								if((tsd->autospell2_id==AL_HEAL || (tsd->autospell2_id==ALL_RESURRECTION && tbl->type != BL_PC)) &&
+									battle_check_undead(status_get_race(tbl),status_get_elem_type(tbl)))
+									f = skill_castend_damage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
 								else
-									f = skill_castend_nodamage_id(target,src,tsd->autospell2_id,skilllv,tick,flag);
+									f = skill_castend_nodamage_id(target,tbl,tsd->autospell2_id,skilllv,tick,flag);
 								break;
 						}
 					}

+ 9 - 6
src/map/map.h

@@ -278,14 +278,17 @@ struct map_session_data {
 	//--- 02/15's new card effects [celest]
 	int crit_atk_rate;
 	int critaddrace[12];
-	int no_regen;
+	short no_regen;
 	int addeff3[10];
-	short autospell2_id,autospell2_lv,autospell2_rate;
+	short autospell2_id,autospell2_lv,autospell2_rate,autospell2_type;
 	int skillatk[2];
 	unsigned short unstripable_equip;
-	short add_damage_classid2[10];
+	short add_damage_classid2[10],add_damage_class_count2;
 	int add_damage_classrate2[10];
-	int add_damage_class_count2;
+	short sp_gain_value;
+	short ignore_def_mob, ignore_def_mob_;
+	int hp_loss_tick, hp_loss_rate;
+	short hp_loss_value, hp_loss_type;
 
 	short spiritball, spiritball_old;
 	int spirit_timer[MAX_SKILL_LEVEL];
@@ -626,8 +629,8 @@ enum {
 	SP_UNBREAKABLE_SHIELD, SP_LONG_ATK_RATE, // 2011-2012
 
 	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_ADD_DAMAGE_BY_CLASS // 2020-2022
+	SP_SKILL_ATK, SP_UNSTRIPABLE, SP_ADD_DAMAGE_BY_CLASS, // 2018-2020
+	SP_SP_GAIN_VALUE, SP_IGNORE_DEF_MOB, SP_HP_LOSS_RATE // 2021-2023
 };
 
 enum {

+ 15 - 10
src/map/mob.c

@@ -2164,8 +2164,7 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 	struct item item;
 	int ret;
 	int drop_rate;
-	int skill,sp;
-
+	
 	nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
 
 	max_hp = status_get_max_hp(&md->bl);
@@ -2384,14 +2383,20 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
 	if(src && src->type == BL_MOB)
 		mob_unlocktarget((struct mob_data *)src,tick);
 
-	/* ソウルドレイン */
-	if(sd && sd->state.attack_type == BF_MAGIC && (skill=pc_checkskill(sd,HW_SOULDRAIN))>0){
-		clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,skill,1);
-		sp = (status_get_lv(&md->bl))*(65+15*skill)/100;
-		if(sd->status.sp + sp > sd->status.max_sp)
-			sp = sd->status.max_sp - sd->status.sp;
-		sd->status.sp += sp;
-		clif_heal(sd->fd,SP_SP,sp);
+	
+	if(sd) {
+		int sp = 0;
+		if (sd->state.attack_type == BF_MAGIC && (i=pc_checkskill(sd,HW_SOULDRAIN))>0){	/* ソウルドレイン */
+			clif_skill_nodamage(src,&md->bl,HW_SOULDRAIN,i,1);
+			sp += (status_get_lv(&md->bl))*(65+15*i)/100;
+		}
+		sp += sd->sp_gain_value;
+		if (sp > 0) {
+			if(sd->status.sp + sp > sd->status.max_sp)
+				sp = sd->status.max_sp - sd->status.sp;
+			sd->status.sp += sp;
+			clif_heal(sd->fd,SP_SP,sp);
+		}
 	}
 
 	// map外に消えた人は計算から除くので

+ 76 - 7
src/map/pc.c

@@ -1575,6 +1575,16 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		if(sd->state.lr_flag != 2)
 			sd->unstripable_equip |= EQP_ARMOR;
 		break;
+	case SP_SP_GAIN_VALUE:
+		if(!sd->state.lr_flag)
+			sd->sp_gain_value += val;
+		break;
+	case SP_IGNORE_DEF_MOB:	// 0:normal monsters only, 1:affects boss monsters as well
+		if(!sd->state.lr_flag)
+			sd->ignore_def_mob |= 1<<val;
+		else if(sd->state.lr_flag == 1)
+			sd->ignore_def_mob_ |= 1<<val;
+		break;
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus: unknown type %d %d !\n",type,val);
@@ -1823,6 +1833,13 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
 			}			
 		}
 		break;
+	case SP_HP_LOSS_RATE:
+		if(sd->state.lr_flag != 2) {
+			sd->hp_loss_value = type2;
+			sd->hp_loss_rate = val;
+		}
+		break;
+
 	default:
 		if(battle_config.error_log)
 			printf("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
@@ -1865,6 +1882,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 			sd->autospell2_id = type2;
 			sd->autospell2_lv = type3;
 			sd->autospell2_rate = val;
+			sd->autospell2_type = 1;	// enemy
 		}
 		break;
 	default:
@@ -1876,6 +1894,26 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
 	return 0;
 }
 
+int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4,int val)
+{
+	switch(type){
+	case SP_AUTOSPELL_WHENHIT:
+		if(sd->state.lr_flag != 2){
+			sd->autospell2_id = type2;
+			sd->autospell2_lv = type3;
+			sd->autospell2_rate = type4;
+			sd->autospell2_type = val;	// 0: self, 1: enemy
+		}
+		break;
+	default:
+		if(battle_config.error_log)
+			printf("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
+		break;
+	}
+
+	return 0;
+}
+
 /*==========================================
  * スクリプトによるスキル所得
  *------------------------------------------
@@ -6513,7 +6551,7 @@ static int pc_natural_heal_sp(struct map_session_data *sd)
 	return 0;
 }
 
-static int pc_spirit_heal_hp(struct map_session_data *sd,int level)
+static int pc_spirit_heal_hp(struct map_session_data *sd)
 {
 	int bonus_hp,interval = battle_config.natural_heal_skill_interval;
 
@@ -6553,7 +6591,7 @@ static int pc_spirit_heal_hp(struct map_session_data *sd,int level)
 
 	return 0;
 }
-static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
+static int pc_spirit_heal_sp(struct map_session_data *sd)
 {
 	int bonus_sp,interval = battle_config.natural_heal_skill_interval;
 
@@ -6594,6 +6632,30 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
 	return 0;
 }
 
+static int pc_bleeding (struct map_session_data *sd)
+{
+	int interval, hp;
+
+	nullpo_retr(0, sd);
+	interval = sd->hp_loss_rate;
+	hp = sd->hp_loss_value;
+
+	sd->hp_loss_tick += natural_heal_diff_tick;
+	if(sd->hp_loss_tick >= interval) {
+		while(sd->hp_loss_tick >= interval) {
+			sd->hp_loss_tick -= interval;
+			if (sd->status.hp < hp)
+				hp = sd->status.hp;
+			if (sd->hp_loss_type == 0) {
+				pc_heal(sd,-hp,0);
+			} else if (sd->hp_loss_type == 1) {
+			}
+			sd->hp_loss_tick = 0;
+		}
+	}
+	return 0;
+}
+
 /*==========================================
  * HP/SP 自然回復 各クライアント
  *------------------------------------------
@@ -6601,15 +6663,17 @@ static int pc_spirit_heal_sp(struct map_session_data *sd,int level)
 
 static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) {
 	int skill;
+	int tick;
 
 	nullpo_retr(0, sd);
+	tick = va_arg(ap,int);
 
 // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
 	if ((battle_config.natural_heal_weight_rate > 100 || sd->weight*100/sd->max_weight < battle_config.natural_heal_weight_rate) &&
 		!pc_isdead(sd) &&
 		!pc_ishiding(sd) &&
 	//-- cannot regen for 5 minutes after using Berserk --- [Celest]
-		DIFF_TICK (gettick(), sd->canregen_tick)>=0 &&
+		DIFF_TICK (tick, sd->canregen_tick)>=0 &&
 		(sd->sc_data && !(sd->sc_data[SC_POISON].timer != -1 && sd->sc_data[SC_SLOWPOISON].timer == -1) &&
 		sd->sc_data[SC_BERSERK].timer == -1 )) {
 		pc_natural_heal_hp(sd);
@@ -6617,20 +6681,25 @@ static int pc_natural_heal_sub(struct map_session_data *sd,va_list ap) {
 			sd->sc_data[SC_DANCING].timer == -1 && //ダンス?態ではSPが回復しない
 			sd->sc_data[SC_BERSERK].timer == -1 )   //バ?サ?ク?態ではSPが回復しない
 			pc_natural_heal_sp(sd);
-		sd->canregen_tick = gettick();
+		sd->canregen_tick = tick;
 	} else {
 		sd->hp_sub = sd->inchealhptick = 0;
 		sd->sp_sub = sd->inchealsptick = 0;
 	}
 	if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0 && !pc_ishiding(sd) &&
 		sd->sc_data[SC_POISON].timer == -1 && sd->sc_data[SC_BERSERK].timer == -1){
-		pc_spirit_heal_hp(sd,skill);
-		pc_spirit_heal_sp(sd,skill);
+		pc_spirit_heal_hp(sd);
+		pc_spirit_heal_sp(sd);
 	}
 	else {
 		sd->inchealspirithptick = 0;
 		sd->inchealspiritsptick = 0;
 	}
+	if (sd->hp_loss_value > 0)
+		pc_bleeding(sd);
+	else
+		sd->hp_loss_tick = 0;
+
 	return 0;
 }
 
@@ -6642,7 +6711,7 @@ int pc_natural_heal(int tid,unsigned int tick,int id,int data)
 {
 	natural_heal_tick = tick;
 	natural_heal_diff_tick = DIFF_TICK(natural_heal_tick,natural_heal_prev_tick);
-	clif_foreachclient(pc_natural_heal_sub);
+	clif_foreachclient(pc_natural_heal_sub, tick);
 
 	natural_heal_prev_tick = tick;
 	return 0;

+ 1 - 0
src/map/pc.h

@@ -89,6 +89,7 @@ int pc_checkweighticon(struct map_session_data *sd);
 int pc_bonus(struct map_session_data*,int,int);
 int pc_bonus2(struct map_session_data *sd,int,int,int);
 int pc_bonus3(struct map_session_data *sd,int,int,int,int);
+int pc_bonus4(struct map_session_data *sd,int,int,int,int,int);
 int pc_skill(struct map_session_data*,int,int,int);
 
 void pc_blockskill_start (struct map_session_data*,int,int);	// [celest]

+ 18 - 0
src/map/script.c

@@ -150,6 +150,7 @@ int buildin_statusup2(struct script_state *st);
 int buildin_bonus(struct script_state *st);
 int buildin_bonus2(struct script_state *st);
 int buildin_bonus3(struct script_state *st);
+int buildin_bonus4(struct script_state *st);
 int buildin_skill(struct script_state *st);
 int buildin_addtoskill(struct script_state *st); // [Valaris]
 int buildin_guildskill(struct script_state *st);
@@ -373,6 +374,7 @@ struct {
 	{buildin_bonus,"bonus","ii"},
 	{buildin_bonus2,"bonus2","iii"},
 	{buildin_bonus3,"bonus3","iiii"},
+	{buildin_bonus4,"bonus4","iiiii"},
 	{buildin_skill,"skill","ii*"},
 	{buildin_addtoskill,"addtoskill","ii*"}, // [Valaris]
 	{buildin_guildskill,"guildskill","ii"},
@@ -3185,6 +3187,22 @@ int buildin_bonus3(struct script_state *st)
 
 	return 0;
 }
+
+int buildin_bonus4(struct script_state *st)
+{
+	int type,type2,type3,type4,val;
+	struct map_session_data *sd;
+
+	type=conv_num(st,& (st->stack->stack_data[st->start+2]));
+	type2=conv_num(st,& (st->stack->stack_data[st->start+3]));
+	type3=conv_num(st,& (st->stack->stack_data[st->start+4]));
+	type4=conv_num(st,& (st->stack->stack_data[st->start+5]));
+	val=conv_num(st,& (st->stack->stack_data[st->start+6]));
+	sd=script_rid2sd(st);
+	pc_bonus4(sd,type,type2,type3,type4,val);
+
+	return 0;
+}
 /*==========================================
  * ƒXƒLƒ‹�Š“¾
  *------------------------------------------

+ 3 - 0
src/map/status.c

@@ -276,6 +276,9 @@ int status_calc_pc(struct map_session_data* sd,int first)
 	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));
+	sd->sp_gain_value = 0;
+	sd->ignore_def_mob = sd->ignore_def_mob_ = 0;
+	sd->hp_loss_rate = sd->hp_loss_value = sd->hp_loss_type = 0;
 
 	if(!sd->disguiseflag && sd->disguise) {
 		sd->disguise=0;