summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt4
-rw-r--r--conf/battle/skill.conf7
-rw-r--r--db/const.txt3
-rw-r--r--db/skill_cast_db.txt4
-rw-r--r--db/skill_db.txt4
-rw-r--r--src/map/battle.c22
-rw-r--r--src/map/battle.h1
-rw-r--r--src/map/clif.c4
-rw-r--r--src/map/mob.c2
-rw-r--r--src/map/mob.h3
-rw-r--r--src/map/script.c75
-rw-r--r--src/map/skill.c15
-rw-r--r--src/map/skill.h5
-rw-r--r--src/map/status.c13
-rw-r--r--src/map/status.h4
15 files changed, 141 insertions, 25 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index d24add8f3..53f6b511c 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -3,6 +3,10 @@ Date Added
AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
+09/06/19
+ * Implemented script command "areamobuseskill" and skill NPC_INVINCIBLE and NPC_INVINCIBLEOFF. (topic:217330) [Inkfish]
+ * Using items no longer cancels invincibility(but using target and ground skills through items does). (bugreport:3259) [Inkfish]
+ * Fixed Butterfly Wings not working during GVG. (bugreport:3264) [Inkfish]
09/06/16
* Fixed an exploit that makes guild skill get higher level than the max defined in guild_skill_tree. (bugreport:3241) [Inkfish]
* Turn Undead won't apply aftercast delay when casted on a "living" entity. (bugreport:1740) [Inkfish]
diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf
index 82a615aba..960960692 100644
--- a/conf/battle/skill.conf
+++ b/conf/battle/skill.conf
@@ -265,4 +265,9 @@ skill_add_heal_rate: 7
// Whether the damage of EarthQuake with a single target on screen is able to be reflected.
// Note: On offcial server, EQ is reflectable when there is only one target on the screen,
// which might be an exploit to hunt the MVPs.
-eq_single_target_reflectable: yes \ No newline at end of file
+eq_single_target_reflectable: yes
+
+// On official server, you will receive damage from Reflection and some Tarot Card even in invincible status.
+// When this setting is enabled, it allows you to immune to all kinds of damage, including those stated previous.
+// (The number will show but no actual damage will be done)
+invincible.nodamage: no \ No newline at end of file
diff --git a/db/const.txt b/db/const.txt
index bd7df1748..b34502b89 100644
--- a/db/const.txt
+++ b/db/const.txt
@@ -817,6 +817,9 @@ SC_S_LIFEPOTION 290
SC_L_LIFEPOTION 291
SC_JEXPBOOST 292
SC_IGNOREDEF 293
+SC_HELLPOWER 294
+SC_INVINCIBLE 295
+SC_INVINCIBLEOFF 296
e_gasp 0
e_what 1
diff --git a/db/skill_cast_db.txt b/db/skill_cast_db.txt
index 0e0b4f438..ff5a63e70 100644
--- a/db/skill_cast_db.txt
+++ b/db/skill_cast_db.txt
@@ -975,6 +975,10 @@
683,0,0,0,0,300000
//-- NPC_WIDEHELLDIGNITY
684,0,0,0,0,300000
+//-- NPC_INVINCIBLE
+685,0,0,0,-1,0
+//-- NPC_INVINCIBLEOFF
+686,0,0,0,60000,0
//===== Item Use-Only Skills ===============
//-- CASH_BLESSING
diff --git a/db/skill_db.txt b/db/skill_db.txt
index fd4754a2c..4573d5015 100644
--- a/db/skill_db.txt
+++ b/db/skill_db.txt
@@ -625,8 +625,8 @@
//682,0,0,0,0,0,0,9,0,no,0,0,0,none,0, NPC_TALK,Talk
683,-9,6,1,-1,0,0,1,1,no,0,0x2,0,none,0, NPC_HELLPOWER,Hell Power
684,0,6,4,0,0x3,-1,1,1,no,0,0x2,0,none,0, NPC_WIDEHELLDIGNITY,Hell Dignity
-//685,0,0,0,0,0,0,9,0,no,0,0,0,none,0, NPC_INVINCIBLE,Incinvible
-//686,0,0,0,0,0,0,9,0,no,0,0,0,none,0, NPC_INVINCIBLEOFF,Invincible off
+685,0,0,4,0,0x1,0,1,1,no,0,0x2,0,none,0, NPC_INVINCIBLE,Incinvible
+686,0,0,4,0,0x1,0,1,1,no,0,0x2,0,none,0, NPC_INVINCIBLEOFF,Invincible off
687,0,6,4,0,0x1,0,1,1,yes,0,0x2,0,none,0, NPC_ALLHEAL,Full Heal
// Additional Skill (??)
diff --git a/src/map/battle.c b/src/map/battle.c
index 0f943c5c4..17f052bb0 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -294,12 +294,15 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if(!damage) return 0;
}
-
- if (skill_num == PA_PRESSURE)
- return damage; //This skill bypass everything else.
sc = status_get_sc(bl);
+ if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
+ return 0;
+
+ if (skill_num == PA_PRESSURE)
+ return damage; //This skill bypass everything else.
+
if( sc && sc->count )
{
//First, sc_*'s that reduce damage to 0.
@@ -482,12 +485,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
status_heal(src, damage*sce->val4/100, 0, 3);
}
- //SC effects from caster side. Currently none.
-/*
+
+ //SC effects from caster side.
sc = status_get_sc(src);
- if (sc && sc->count) {
+
+ if (sc && sc->count)
+ {
+ if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
+ damage += damage * 75 / 100;
}
-*/
+
if (battle_config.pk_mode && sd && bl->type == BL_PC && damage)
{
if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
@@ -3820,6 +3827,7 @@ static const struct _battle_data {
{ "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, },
{ "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, },
{ "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, },
+ { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
// BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, },
diff --git a/src/map/battle.h b/src/map/battle.h
index c559c0ba5..8e262cc5e 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -466,6 +466,7 @@ extern struct Battle_Config
int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara]
int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish]
int eq_single_target_reflectable;
+ int invincible_nodamage;
// [BattleGround Settings]
int bg_update_interval;
diff --git a/src/map/clif.c b/src/map/clif.c
index ddb0fcca8..7a16ab73b 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -8940,8 +8940,6 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
} else
if (pc_istrading(sd))
return;
-
- pc_delinvincibletimer(sd);
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
sd->idletime = last_tick;
@@ -9510,6 +9508,8 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
{
if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
+ if( !(skill_get_inf(skillnum)&INF_SELF_SKILL) )
+ pc_delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish]
unit_skilluse_id(&sd->bl, target_id, skillnum, skilllv);
return;
}
diff --git a/src/map/mob.c b/src/map/mob.c
index 834d44220..367d2ff7d 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -50,8 +50,6 @@
#define MOB_MAX_DELAY (24*3600*1000)
#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
-//Used to determine default enemy type of mobs (for use in eachinrange calls)
-#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_PC|BL_HOM|BL_MER)
//Dynamic mob database, allows saving of memory when there's big gaps in the mob_db [Skotlex]
struct mob_db *mob_db_data[MAX_MOB_DB+1];
diff --git a/src/map/mob.h b/src/map/mob.h
index b0a7a11e9..360c69e06 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -35,6 +35,9 @@
#define MOB_CLONE_START (MAX_MOB_DB-999)
#define MOB_CLONE_END MAX_MOB_DB
+//Used to determine default enemy type of mobs (for use in eachinrange calls)
+#define DEFAULT_ENEMY_TYPE(md) (md->special_state.ai?BL_CHAR:BL_PC|BL_HOM|BL_MER)
+
//Mob skill states.
enum MobSkillState {
MSS_ANY = -1,
diff --git a/src/map/script.c b/src/map/script.c
index f09b24a5c..28cea9ed1 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -13655,6 +13655,80 @@ BUILDIN_FUNC(setfont)
return 0;
}
+static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap)
+{
+ TBL_MOB* md = (TBL_MOB*)bl;
+ struct block_list *tbl;
+ int mobid = va_arg(ap,int);
+ int skillid = va_arg(ap,int);
+ int skilllv = va_arg(ap,int);
+ int casttime = va_arg(ap,int);
+ int cancel = va_arg(ap,bool);
+ int emotion = va_arg(ap,int);
+ int target = va_arg(ap,int);
+
+ if( md->class_ != mobid )
+ return 0;
+
+ if( md->ud.skilltimer != -1 ) // Cancel the casting skill.
+ unit_skillcastcancel(bl,0);
+
+ // 0:self, 1:target, 2:master, default:random
+ switch( target )
+ {
+ case 0: tbl = map_id2bl(md->bl.id); break;
+ case 1: tbl = map_id2bl(md->target_id); break;
+ case 2: tbl = map_id2bl(md->master_id); break;
+ default:tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill_get_range2(&md->bl, skillid, skilllv)); break;
+ }
+
+ if( !tbl )
+ return 0;
+
+ if( skill_get_casttype(skillid) == CAST_GROUND )
+ unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skillid, skilllv, casttime, cancel);
+ else
+ unit_skilluse_id2(&md->bl, tbl->id, skillid, skilllv, casttime, cancel);
+
+ clif_emotion(&md->bl, emotion);
+
+ return 0;
+}
+/*==========================================
+ * areamobuseskill "Map Name",<x1>,<y1>,<x2>,<y2>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>;
+ *------------------------------------------*/
+BUILDIN_FUNC(areamobuseskill)
+{
+ int m,x1,y1,x2,y2,mobid,skillid,skilllv,casttime,emotion,target;
+ bool cancel;
+
+ if( m = map_mapname2mapid(script_getstr(st,2)) < 0 )
+ {
+ ShowError("areamobuseskill: invalid map name.\n");
+ return 0;
+ }
+
+ skillid = ( script_isstring(st,8) ? skill_name2id(script_getstr(st,8)) : script_getnum(st,8) );
+
+ skilllv = script_getnum(st,9);
+ if( skilllv > battle_config.mob_max_skilllvl )
+ skilllv = battle_config.mob_max_skilllvl;
+
+ x1 = script_getnum(st,3);
+ y1 = script_getnum(st,4);
+ x2 = script_getnum(st,5);
+ y2 = script_getnum(st,6);
+
+ mobid = script_getnum(st,7);
+ casttime = script_getnum(st,10);
+ cancel = script_getnum(st,11);
+ emotion = script_getnum(st,12);
+ target = script_getnum(st,13);
+
+ map_foreachinarea(buildin_mobuseskill_sub, m, x1, y1, x2, y2, BL_MOB, mobid,skillid,skilllv,casttime,cancel,emotion,target);
+ return 0;
+}
+
// declarations that were supposed to be exported from npc_chat.c
#ifdef PCRE_SUPPORT
BUILDIN_FUNC(defpattern);
@@ -14014,6 +14088,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(mercenary_set_faith,"ii"),
BUILDIN_DEF(readbook,"ii"),
BUILDIN_DEF(setfont,"i"),
+ BUILDIN_DEF(areamobuseskill,"siiiiiviiiii"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
BUILDIN_DEF(agitend2,""),
diff --git a/src/map/skill.c b/src/map/skill.c
index f33b7bb59..ef3b65dac 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -360,7 +360,10 @@ int skillnotok (int skillid, struct map_session_data *sd)
return 1; // invalid skill id
if (battle_config.gm_skilluncond && pc_isGM(sd) >= battle_config.gm_skilluncond)
- return 0; // GMs can do any damn thing they want
+ return 0; // GMs can do any damn thing they want
+
+ if( skillid == AL_TELEPORT && sd->skillitem == skillid && sd->skillitemlv > 2 )
+ return 0; // Teleport lv 3 bypasses this check.[Inkfish]
if (sd->blockskill[i] > 0)
return 1;
@@ -385,10 +388,10 @@ int skillnotok (int skillid, struct map_session_data *sd)
}
return 0;
case AL_TELEPORT:
- // if(map[m].flag.noteleport) {
- // clif_skill_teleportmessage(sd,0);
- // return 1;
- // }
+ if(map[m].flag.noteleport) {
+ clif_skill_teleportmessage(sd,0);
+ return 1;
+ }
return 0; // gonna be checked in 'skill_castend_nodamage_id'
case WE_CALLPARTNER:
case WE_CALLPARENT:
@@ -3662,6 +3665,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
case NPC_DEFENDER:
case NPC_MAGICMIRROR:
case ST_PRESERVE:
+ case NPC_INVINCIBLE:
+ case NPC_INVINCIBLEOFF:
clif_skill_nodamage(src,bl,skillid,skilllv,
sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)));
break;
diff --git a/src/map/skill.h b/src/map/skill.h
index 795cdf65b..02a9a760a 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -972,15 +972,12 @@ enum e_skill {
NPC_WIDESOULDRAIN,
ALL_INCCARRY = 681,
-
//NPC_TALK = 682,
NPC_HELLPOWER = 683,
NPC_WIDEHELLDIGNITY,
- /*
NPC_INVINCIBLE,
NPC_INVINCIBLEOFF,
- */
- NPC_ALLHEAL = 687,
+ NPC_ALLHEAL,
//GM_SANDMAN = 688,
CASH_BLESSING = 689,
CASH_INCAGI,
diff --git a/src/map/status.c b/src/map/status.c
index 54d019a48..467626106 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -388,6 +388,8 @@ void initChangeTables(void)
set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
+ set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED );
+ set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED );
set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
set_sc( CASH_INCAGI , SC_INCREASEAGI , SI_INCREASEAGI , SCB_AGI|SCB_SPEED );
@@ -665,6 +667,13 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
sc = status_get_sc(target);
+ if( battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
+ {
+ if( !sp )
+ return 0;
+ hp = 0;
+ }
+
if( hp && !(flag&1) ) {
if( sc ) {
struct status_change_entry *sce;
@@ -3798,6 +3807,8 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
val = max( val, 55 );
if( sc->data[SC_AVOID] )
val = max( val, 10 * sc->data[SC_AVOID]->val1 );
+ if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
+ val = max( val, 75 );
//FIXME: official items use a single bonus for this [ultramage]
if( sc->data[SC_SPEEDUP0] ) // temporary item-based speedup
@@ -3822,7 +3833,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
speed = 200;
if( sc->data[SC_DEFENDER] )
speed = max(speed, 200);
- if( sc->data[SC_WALKSPEED] ) // ChangeSpeed
+ if( sc->data[SC_WALKSPEED] && sc->data[SC_WALKSPEED]->val1 > 0 ) // ChangeSpeed
speed = speed * 100 / sc->data[SC_WALKSPEED]->val1;
}
diff --git a/src/map/status.h b/src/map/status.h
index 389817a65..2d45b2626 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -315,6 +315,8 @@ typedef enum sc_type {
SC_JEXPBOOST,
SC_IGNOREDEF,
SC_HELLPOWER,
+ SC_INVINCIBLE, //295
+ SC_INVINCIBLEOFF,
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
@@ -633,7 +635,7 @@ enum si_type {
// SI_REUSE_LIMIT_D = 308,
// SI_REUSE_LIMIT_E = 309,
// SI_REUSE_LIMIT_F = 310,
-// SI_INVINCIBLE = 311,
+ SI_INVINCIBLE = 311,
SI_CASH_PLUSONLYJOBEXP = 312,
// SI_PARTYFLEE = 313,
// SI_ANGEL_PROTECT = 314,