Преглед на файлове

Updated Feint Bomb to match official behavior
* Fixes #728 and fixes #1070.
* Players can no longer use skills while in the hidden state from Feint Bomb.
* Targets will now properly release the caster as a target and follow the bomb.
Thanks to @Tokeiburu, @MrAntares, and @stealth62!

aleos преди 8 години
родител
ревизия
caed38927a
променени са 2 файла, в които са добавени 43 реда и са изтрити 16 реда
  1. 42 8
      src/map/skill.c
  2. 1 8
      src/map/status.c

+ 42 - 8
src/map/skill.c

@@ -321,6 +321,7 @@ static int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsig
 int skill_unit_onleft(uint16 skill_id, struct block_list *bl,unsigned int tick);
 static int skill_unit_effect(struct block_list *bl,va_list ap);
 static int skill_bind_trap(struct block_list *bl, va_list ap);
+static int skill_mob_releasetarget(struct block_list *bl, va_list ap);
 
 int skill_get_casttype (uint16 skill_id) {
 	int inf = skill_get_inf(skill_id);
@@ -11990,10 +11991,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 		if( sd ) clif_magicdecoy_list(sd,skill_lv,x,y);
 		break;
 
-	case SC_FEINTBOMB:
-		skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
-		skill_blown(src, src, skill_get_blewcount(skill_id, skill_lv), unit_getdir(src), BLOWN_IGNORE_NO_KNOCKBACK); // Don't stop the caster from backsliding if special_state.no_knockback is active
-		clif_skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,skill_get_time2(skill_id,skill_lv)));
+	case SC_FEINTBOMB: {
+			struct skill_unit_group *group = skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position
+
+			map_foreachinrange(skill_mob_releasetarget, src, AREA_SIZE, BL_MOB, src, &group->unit->bl); // Release all targets against the caster.
+			skill_blown(src, src, skill_get_blewcount(skill_id, skill_lv), unit_getdir(src), BLOWN_IGNORE_NO_KNOCKBACK); // Don't stop the caster from backsliding if special_state.no_knockback is active
+			clif_skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,src,type,100,skill_lv,skill_get_time2(skill_id,skill_lv)));
+		}
 		break;
 
 	case SC_ESCAPE:
@@ -17096,6 +17100,38 @@ static int skill_bind_trap(struct block_list *bl, va_list ap) {
 	return 1;
 }
 
+/**
+ * Release monsters that are targetting the caster and change target.
+ * @param bl: Monster data
+ * @param src: Player data
+ * @param skill: Skill unit group data
+ */
+static int skill_mob_releasetarget(struct block_list *bl, va_list ap)
+{
+	struct block_list *src = NULL, *skill = NULL;
+	struct mob_data *md = NULL;
+
+	nullpo_ret(bl);
+	nullpo_ret(ap);
+	nullpo_ret(src = va_arg(ap, struct block_list *));
+	nullpo_ret(skill = va_arg(ap, struct block_list *));
+
+	if (bl->type != BL_MOB)
+		return 0;
+
+	md = map_id2md(bl->id);
+
+	if (md && md->target_id == src->id) {
+		struct unit_data *ud = unit_bl2ud(bl);
+
+		md->attacked_id = 0;
+		md->target_id = skill->id;
+		ud->target_to = skill->id;
+	}
+
+	return 1;
+}
+
 /*==========================================
  * Check new skill unit cell when overlapping in other skill unit cell.
  * Catched skill in cell value pushed to *unit pointer.
@@ -18201,11 +18237,9 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
 
 			case UNT_FEINTBOMB: {
 				struct block_list *src = map_id2bl(group->src_id);
-				struct status_change *sc;
-				if (src && (sc = status_get_sc(src)) != NULL && sc->data[SC__FEINTBOMB]) { // Copycat explodes if caster is still hidden.
+
+				if (src)
 					map_foreachinrange(skill_area_sub, &unit->bl, unit->range, BL_CHAR|BL_SKILL, src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|5, skill_castend_damage_id);
-					status_change_end(bl, SC__FEINTBOMB, INVALID_TIMER);
-				}
 				skill_delunit(unit);
 			}
 			break;

+ 1 - 8
src/map/status.c

@@ -1385,6 +1385,7 @@ void initChangeTables(void)
 	StatusChangeStateTable[SC_CRYSTALIZE]			|= SCS_NOCAST;
 	StatusChangeStateTable[SC__IGNORANCE]			|= SCS_NOCAST;
 	StatusChangeStateTable[SC__MANHOLE]				|= SCS_NOCAST;
+	StatusChangeStateTable[SC__FEINTBOMB]			|= SCS_NOCAST;
 	StatusChangeStateTable[SC_DEEPSLEEP]			|= SCS_NOCAST;
 	StatusChangeStateTable[SC_SATURDAYNIGHTFEVER]	|= SCS_NOCAST;
 	StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET]	|= SCS_NOCAST;
@@ -11974,14 +11975,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 				if (s_sd) s_sd->shadowform_id = 0;
 			}
 			break;
-		case SC__FEINTBOMB:
-			if( sd && pc_ishiding(sd) ) {
-				status_change_end(bl, SC_HIDING, INVALID_TIMER);
-				status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
-				status_change_end(bl, SC_CHASEWALK, INVALID_TIMER);
-				status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER);
-			}
-			break;
 		case SC_SATURDAYNIGHTFEVER: // Sit down force of Saturday Night Fever has the duration of only 3 seconds.
 			sc_start(bl, bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1));
 			break;