Parcourir la source

Monster AI Improvements, Clashing Spiral, Skid Trap, Throw Stone (#8269)

- Added config setting mob_unlock_time that defines how long a monster can be trapped (immobile) before it unlocks its target 
  * Default is 2000ms, which makes Clashing Spiral no longer cause monsters to drop their target, but Ankle Snare still will even at minimum duration 
- Monsters will now promptly use idle skills while trapped (there was a delay before)
- Increased the time the AI is still active when there are no players left on the map from 0ms to 5000ms
  * This fixes an issue that monsters never unlocked their target if it was the last player to leave the map
- Clashing Spiral now has a range of 4 instead of 5
- Skid Trap no longer has a stop effect in pre-re, but it will make monsters unlock their target and become idle
- Skid Trap still stops targets for 3 seconds in renewal, but will no longer activate on bosses
- Throw Stone now deals 30 damage when used by monsters
- Fixes #7846
Playtester il y a 1 an
Parent
commit
f15cb72f94
8 fichiers modifiés avec 49 ajouts et 22 suppressions
  1. 9 4
      conf/battle/monster.conf
  2. 2 3
      db/pre-re/skill_db.yml
  3. 2 2
      db/re/skill_db.yml
  4. 7 3
      src/map/battle.cpp
  5. 1 0
      src/map/battle.hpp
  6. 17 6
      src/map/mob.cpp
  7. 1 1
      src/map/mob.hpp
  8. 10 3
      src/map/skill.cpp

+ 9 - 4
conf/battle/monster.conf

@@ -79,10 +79,10 @@ monster_chase_refresh: 30
 // 8: Enable mob-warping when standing on Dimensional Door
 mob_warp: 0
 
-// If these are set above 0, they define the time (in ms) during which monsters
-// will have their 'AI' active after all players have left their vicinity.
-mob_active_time: 0
-boss_active_time: 0
+// Defines the time (in ms) during which monsters will have their AI active
+// after all players have left their vicinity.
+mob_active_time: 5000
+boss_active_time: 5000
 
 // Mobs and Pets view-range adjustment (range2 column in the mob_db) (Note 2)
 view_range_rate: 100
@@ -302,3 +302,8 @@ slave_stick_with_master: no
 // Also used in delaying the spawning of guardians when a guild is not loaded.
 // Default (Official): 1000
 mob_respawn_time: 1000
+
+// Defines the time (in ms) after which a monster unlocks its target when trapped.
+// During this time monsters will still be in idle mode and use idle skills on random
+// targets, but they continue chasing their original target when no longer trapped.
+mob_unlock_time: 2000

+ 2 - 3
db/pre-re/skill_db.yml

@@ -4153,7 +4153,6 @@ Body:
         Time: 120000
       - Level: 5
         Time: 60000
-    Duration2: 3000
     Requires:
       SpCost: 10
       ItemCost:
@@ -10805,7 +10804,7 @@ Body:
       IgnoreDefense: true
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -32756,7 +32755,7 @@ Body:
       IgnoreDefense: true
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon

+ 2 - 2
db/re/skill_db.yml

@@ -11048,7 +11048,7 @@ Body:
     TargetType: Attack
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon
@@ -46222,7 +46222,7 @@ Body:
     TargetType: Attack
     Flags:
       TargetTrap: true
-    Range: 5
+    Range: 4
     Hit: Multi_Hit
     HitCount: 5
     Element: Weapon

+ 7 - 3
src/map/battle.cpp

@@ -8940,7 +8940,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
 
 	switch (skill_id) {
 		case TF_THROWSTONE:
-			md.damage = 50;
+			if (sd)
+				md.damage = 50;
+			else
+				md.damage = 30;
 			md.flag |= BF_WEAPON;
 			break;
 		case NPC_KILLING_AURA:
@@ -11126,8 +11129,8 @@ static const struct _battle_data {
 	{ "day_duration",                       &battle_config.day_duration,                    0,      0,      INT_MAX,        },
 	{ "night_duration",                     &battle_config.night_duration,                  0,      0,      INT_MAX,        },
 	{ "mob_remove_delay",                   &battle_config.mob_remove_delay,                60000,  1000,   INT_MAX,        },
-	{ "mob_active_time",                    &battle_config.mob_active_time,                 0,      0,      INT_MAX,        },
-	{ "boss_active_time",                   &battle_config.boss_active_time,                0,      0,      INT_MAX,        },
+	{ "mob_active_time",                    &battle_config.mob_active_time,                 5000,   0,      INT_MAX,        },
+	{ "boss_active_time",                   &battle_config.boss_active_time,                5000,   0,      INT_MAX,        },
 	{ "sg_miracle_skill_duration",          &battle_config.sg_miracle_skill_duration,       3600000, 0,     INT_MAX,        },
 	{ "hvan_explosion_intimate",            &battle_config.hvan_explosion_intimate,         45000,  0,      100000,         },
 	{ "quest_exp_rate",                     &battle_config.quest_exp_rate,                  100,    0,      INT_MAX,        },
@@ -11377,6 +11380,7 @@ static const struct _battle_data {
 	{ "feature.dynamicnpc_direction",       &battle_config.feature_dynamicnpc_direction,    0,      0,      1,              },
 
 	{ "mob_respawn_time",                   &battle_config.mob_respawn_time,                1000,   1000,   INT_MAX,        },
+	{ "mob_unlock_time",                    &battle_config.mob_unlock_time,                 2000,   0,      INT_MAX,        },
 
 	{ "feature.stylist",                    &battle_config.feature_stylist,                 1,      0,      1,              },
 	{ "feature.banking_state_enforce",      &battle_config.feature_banking_state_enforce,   0,      0,      1,              },

+ 1 - 0
src/map/battle.hpp

@@ -746,6 +746,7 @@ struct Battle_Config
 	int feature_dynamicnpc_direction;
 
 	int mob_respawn_time;
+	int mob_unlock_time;
 
 	int feature_stylist;
 	int feature_banking_state_enforce;

+ 17 - 6
src/map/mob.cpp

@@ -1164,6 +1164,7 @@ int mob_spawn (struct mob_data *md)
 	md->last_linktime = tick;
 	md->dmgtick = tick - 5000;
 	md->last_pcneartime = 0;
+	md->last_canmove = tick;
 
 	t_tick c = tick - MOB_MAX_DELAY;
 
@@ -1720,6 +1721,8 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 	mode = status_get_mode(&md->bl);
 
 	can_move = (mode&MD_CANMOVE) && unit_can_move(&md->bl);
+	if (can_move)
+		md->last_canmove = tick;
 
 	if (md->target_id)
 	{	//Check validity of current target. [Skotlex]
@@ -1956,13 +1959,21 @@ static bool mob_ai_sub_hard(struct mob_data *md, t_tick tick)
 		&& mob_is_chasing(md->state.skillstate))
 		return true;
 
-	//Out of range...
-	if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0))
-	{	//Can't chase. Immobile and trapped mobs should unlock target and use an idle skill.
+	// Out of range
+	if (!(mode&MD_CANMOVE) || (!can_move && (md->sc.cant.move || DIFF_TICK(tick, md->ud.canmove_tick) > 0)))
+	{	// Can't chase. Immobile and trapped mobs will use idle skills and unlock their target after a while
 		if (md->ud.attacktimer == INVALID_TIMER)
-		{ //Only unlock target if no more attack delay left
-			//This handles triggering idle/walk skill.
-			mob_unlocktarget(md,tick);
+		{ // Only switch mode if no more attack delay left
+			if (DIFF_TICK(tick, md->last_canmove) > battle_config.mob_unlock_time) {
+				// Unlock target or use idle/walk skill
+				mob_unlocktarget(md, tick);
+			}
+			else {
+				// Use idle skill but keep target for now
+				md->state.skillstate = MSS_IDLE;
+				if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
+					mobskill_use(md, tick, -1);
+			}
 		}
 		return true;
 	}

+ 1 - 1
src/map/mob.hpp

@@ -359,7 +359,7 @@ struct mob_data {
 	int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
 	int bg_id; // BattleGround System
 
-	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick;
+	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick,last_canmove;
 	short move_fail_count;
 	short lootitem_count;
 	short min_chase;

+ 10 - 3
src/map/skill.cpp

@@ -16192,8 +16192,15 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t
 				sg->unit_id = UNT_USED_TRAPS;
 				clif_changetraplook(&unit->bl, UNT_USED_TRAPS);
 				sg->limit=DIFF_TICK(tick,sg->tick)+1500;
-				//Target will be stopped for 3 seconds
+#ifdef RENEWAL
+				// In renewal, target will be stopped for 3 seconds
 				sc_start(ss,bl,SC_STOP,100,0,skill_get_time2(sg->skill_id,sg->skill_lv));
+#else
+				// In pre-renewal, if target was a monster, it will unlock target and become idle
+				struct mob_data* md = BL_CAST(BL_MOB, bl);
+				if (md)
+					mob_unlocktarget(md, tick);
+#endif
 			}
 			break;
 
@@ -21256,8 +21263,8 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap)
 		return 0; //AoE skills are ineffective. [Skotlex]
 
 #ifdef RENEWAL
-	// Ankle Snare can no longer trap bosses in renewal
-	if (group->unit_id == UNT_ANKLESNARE && status_bl_has_mode(bl, MD_STATUSIMMUNE))
+	// Ankle Snare and Skid Trap can no longer trap bosses in renewal
+	if ((group->unit_id == UNT_ANKLESNARE || group->unit_id == UNT_SKIDTRAP) && status_bl_has_mode(bl, MD_STATUSIMMUNE))
 		return 0;
 #endif