summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-SVN.txt8
-rw-r--r--db/const.txt9
-rw-r--r--doc/item_bonus.txt7
-rw-r--r--src/map/battle.c28
-rw-r--r--src/map/map.h15
-rw-r--r--src/map/mob.c25
-rw-r--r--src/map/pc.c83
-rw-r--r--src/map/pc.h1
-rw-r--r--src/map/script.c18
-rw-r--r--src/map/status.c3
10 files changed, 162 insertions, 35 deletions
diff --git a/Changelog-SVN.txt b/Changelog-SVN.txt
index bbbe894e7..8b48759d4 100644
--- a/Changelog-SVN.txt
+++ b/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]
diff --git a/db/const.txt b/db/const.txt
index e8cd07893..a2f199c0b 100644
--- a/db/const.txt
+++ b/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 \ No newline at end of file
diff --git a/doc/item_bonus.txt b/doc/item_bonus.txt
index 818a1980f..476c8ff6d 100644
--- a/doc/item_bonus.txt
+++ b/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%
diff --git a/src/map/battle.c b/src/map/battle.c
index 35b1d2737..634b04a70 100644
--- a/src/map/battle.c
+++ b/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:/* 支援系 */
- 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;
}
}
diff --git a/src/map/map.h b/src/map/map.h
index 4c5dbb15e..d4cd5084e 100644
--- a/src/map/map.h
+++ b/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 {
diff --git a/src/map/mob.c b/src/map/mob.c
index 15f06f940..b32db9966 100644
--- a/src/map/mob.c
+++ b/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外に消えた人は計算から除くので
diff --git a/src/map/pc.c b/src/map/pc.c
index c8ab8fae4..78d7102b8 100644
--- a/src/map/pc.c
+++ b/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;
diff --git a/src/map/pc.h b/src/map/pc.h
index 067c3af81..f7fd924fd 100644
--- a/src/map/pc.h
+++ b/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]
diff --git a/src/map/script.c b/src/map/script.c
index 263aba6bc..ce70b29c3 100644
--- a/src/map/script.c
+++ b/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;
+}
/*==========================================
* スキル所得
*------------------------------------------
diff --git a/src/map/status.c b/src/map/status.c
index d6a8b1a22..55f4326f9 100644
--- a/src/map/status.c
+++ b/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;