瀏覽代碼

Prevent Skill Usage after Normal Attacks for Players (#9156)

- Normal attacks now prevent players from using skills for AttackMotion+[200-MaxASPD]*10
  * This is the same delay that is already applied when parrying
- Improved structure of unit_set_attackdelay
  * Now uses an event enum so we know from where it was called
- Fixes #9154
Playtester 2 月之前
父節點
當前提交
a2e19222f2
共有 3 個文件被更改,包括 35 次插入16 次删除
  1. 1 1
      src/map/battle.cpp
  2. 22 14
      src/map/unit.cpp
  3. 12 1
      src/map/unit.hpp

+ 1 - 1
src/map/battle.cpp

@@ -1532,7 +1532,7 @@ bool battle_status_block_damage(struct block_list *src, struct block_list *targe
 
 	if ((sce = sc->getSCE(SC_PARRYING)) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd() % 100 < sce->val2) {
 		clif_skill_nodamage(target, *target, LK_PARRYING, sce->val1);
-		unit_set_attackdelay(*target, gettick());
+		unit_set_attackdelay(*target, gettick(), DELAY_EVENT_PARRY);
 		return false;
 	}
 

+ 22 - 14
src/map/unit.cpp

@@ -1828,14 +1828,12 @@ TIMER_FUNC(unit_resume_running){
 
 /**
  * Sets the delays that prevent attacks and skill usage considering the bl type
- * Officially it just remembers the last attack time here and applies the delays during the comparison
- * But we pre-calculate the delays instead and store them in attackabletime and canact_tick
- * Currently these delays are only applied to PCs
- * TODO: This function should also be called on attacks and cast begin
+ * TODO: Currently this function is only called for normal attacks and parry events and is a work-in-progress
  * @param bl Object to apply attack delay to
  * @param tick Current tick
+ * @param event The event that resulted in calling this function
  */
-void unit_set_attackdelay(block_list& bl, t_tick tick)
+void unit_set_attackdelay(block_list& bl, t_tick tick, e_delay_event event)
 {
 	unit_data* ud = unit_bl2ud(&bl);
 
@@ -1844,16 +1842,26 @@ void unit_set_attackdelay(block_list& bl, t_tick tick)
 
 	switch (bl.type) {
 		case BL_PC:
-			ud->attackabletime = tick + status_get_adelay(&bl);
-			// A fixed delay is added here which is equal to the minimum attack motion you can get
-			// This ensures that at max ASPD attackabletime and canact_tick are equal
-			ud->canact_tick = tick + status_get_amotion(&bl) + (pc_maxaspd(reinterpret_cast<map_session_data*>(&bl)) / AMOTION_DIVIDER_PC);
-			break;
-		case BL_MER:
-			// TODO: Should set this, but only for ground skills
+			switch (event) {
+				case DELAY_EVENT_ATTACK:
+				case DELAY_EVENT_PARRY:
+					// TODO: This should also happen on cast begin
+					// Officially for players it just remembers the last attack time here and applies the delays during the comparison
+					// But we pre-calculate the delays instead and store them in attackabletime and canact_tick
+					ud->attackabletime = tick + status_get_adelay(&bl);
+					// A fixed delay is added here which is equal to the minimum attack motion you can get
+					// This ensures that at max ASPD attackabletime and canact_tick are equal
+					ud->canact_tick = tick + status_get_amotion(&bl) + (pc_maxaspd(reinterpret_cast<map_session_data*>(&bl)) / AMOTION_DIVIDER_PC);
+					break;
+			}
 			break;
 		default:
-			// Not applicable
+			switch (event) {
+				case DELAY_EVENT_ATTACK:
+					// This represents setting of attack delay (recharge time) that happens for non-PCs
+					ud->attackabletime = tick + status_get_adelay(&bl);
+					break;
+			}
 			break;
 	}
 }
@@ -3147,7 +3155,7 @@ static int32 unit_attack_timer_sub(struct block_list* src, int32 tid, t_tick tic
 		if( ud->attacktarget_lv == ATK_NONE )
 			return 1;
 
-		ud->attackabletime = tick + sstatus->adelay;
+		unit_set_attackdelay(*src, tick, DELAY_EVENT_ATTACK);
 
 		// Only reset skill_id here if no skilltimer is currently ongoing
 		if (ud->skilltimer == INVALID_TIMER)

+ 12 - 1
src/map/unit.hpp

@@ -119,6 +119,17 @@ enum e_unit_stop_walking {
 	USW_ALL = 0x1f,
 };
 
+/// Enum for delay events
+enum e_delay_event {
+	DELAY_EVENT_ATTACK = 1, /// Executed a normal attack
+	DELAY_EVENT_CASTBEGIN_ID, /// Started casting a target skill
+	DELAY_EVENT_CASTBEGIN_POS, /// Started casting a ground skill
+	DELAY_EVENT_CASTEND, /// Finished casting a skill
+	DELAY_EVENT_CASTCANCEL, /// Skill cast was cancelled
+	DELAY_EVENT_DAMAGED, /// Got damaged
+	DELAY_EVENT_PARRY, /// Parry activated
+};
+
 // PC, MOB, PET
 
 // Does walk action for unit
@@ -137,7 +148,7 @@ bool unit_can_move(struct block_list *bl);
 int32 unit_is_walking(struct block_list *bl);
 
 // Delay functions
-void unit_set_attackdelay(block_list& bl, t_tick tick);
+void unit_set_attackdelay(block_list& bl, t_tick tick, e_delay_event event);
 int32 unit_set_walkdelay(struct block_list *bl, t_tick tick, t_tick delay, int32 type);
 
 t_tick unit_get_walkpath_time(struct block_list& bl);