Browse Source

* Implemented script command "areamobuseskill" and skill NPC_INVINCIBLE and NPC_INVINCIBLEOFF. (topic:217330)
* Using items no longer cancels invincibility(but using target and ground skills through items does). (bugreport:3259)
* Fixed Butterfly Wings not working during GVG. (bugreport:3264)


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

Inkfish 16 years ago
parent
commit
1d90917604
15 changed files with 141 additions and 25 deletions
  1. 4 0
      Changelog-Trunk.txt
  2. 6 1
      conf/battle/skill.conf
  3. 3 0
      db/const.txt
  4. 4 0
      db/skill_cast_db.txt
  5. 2 2
      db/skill_db.txt
  6. 15 7
      src/map/battle.c
  7. 1 0
      src/map/battle.h
  8. 2 2
      src/map/clif.c
  9. 0 2
      src/map/mob.c
  10. 3 0
      src/map/mob.h
  11. 75 0
      src/map/script.c
  12. 10 5
      src/map/skill.c
  13. 1 4
      src/map/skill.h
  14. 12 1
      src/map/status.c
  15. 3 1
      src/map/status.h

+ 4 - 0
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]

+ 6 - 1
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
+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

+ 3 - 0
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

+ 4 - 0
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

+ 2 - 2
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 (??)

+ 15 - 7
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,        },

+ 1 - 0
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;

+ 2 - 2
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;
 	}

+ 0 - 2
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];

+ 3 - 0
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,

+ 75 - 0
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,""),

+ 10 - 5
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;

+ 1 - 4
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,

+ 12 - 1
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;
 	}
 

+ 3 - 1
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,