Me ocorreu voltar ao básico, voltar naquela fonte chamada Lview e ver como eles fizeram a previsão na hora sem nem usar o módulo AiManager.
O qual adaptei para a contemporaneidade usando algumas questões do AiManager como o Velocity para trabalhar a orientação e os waypoints (apesar de não fazer nenhuma análise com os waypoints a não ser validar a quantidade para detectar se está se movendo ou não)
E bem, meu módulo está em Golang, então desculpe a mudança de idioma.
Resolvi voltar a esta humilde função pois li em algum lugar que prever com base em waypoints é menos preciso do que prever por extrapolação, devido ao número de cliques que os inimigos costumam fazer.
Versão LVIEW:
Código:
# Returns a point where the mouse should click to cast a spells taking into account the targets movement speed def castpoint_for_collision(game, spell, caster, target): global Spells print('predicted') if spell.name not in Spells: return None # Get extra data for spell that isnt provided by lview spell_extra = Spells[spell.name] if len(spell_extra.missiles) > 0: missile = game.get_spell_info(spell_extra.missiles[0]) else: missile = spell t_delay = spell.delay + spell_extra.delay if missile.travel_time > 0.0: t_missile = missile.travel_time else: t_missile = (missile.cast_range / missile.speed) if len(spell_extra.missiles) > 0 and missile.speed > 0.0 else 0.0 # Get direction of target target_dir = target.pos.sub(target.prev_pos).normalize() if math.isnan(target_dir.x): target_dir.x = 0.0 if math.isnan(target_dir.y): target_dir.y = 0.0 if math.isnan(target_dir.z): target_dir.z = 0.0 #print(f'{target_dir.x} {target_dir.y} {target_dir.z}') # If the spell is a line we simulate the main missile to get the collision point if spell_extra.flags & SFlag.Line: iterations = int(missile.cast_range/30.0) step = t_missile/iterations last_dist = 9999999 last_target_pos = None for i in range(iterations): t = i*step target_future_pos = target.pos.add(target_dir.scale((t_delay + t)*target.movement_speed)) spell_dir = target_future_pos.sub(caster.pos).normalize().scale(t*missile.speed) spell_future_pos = caster.pos.add(spell_dir) dist = target_future_pos.distance(spell_future_pos) #print(dist) if dist < missile.width/2.0: return target_future_pos elif dist > last_dist: return last_target_pos else: last_dist = dist last_target_pos = target_future_pos return None # If the spell is an area spell we return the position of the player when the spell procs elif spell_extra.flags & SFlag.Area: return target.pos.add(target_dir.scale((t_delay + t_missile)*target.movement_speed)) else: return target.posminha versão:
Código:
// Returns a point where the mouse should click to cast a spells taking into account the targets movement speed func Castpoint_for_collision(input PredictionInput, pingCheck, checkCollision bool) PredictionOutput { var delay float32 = 0 var t_missile float32 if input.Speed > 0 { t_missile = input.Range / input.Speed } else { t_missile = 0 } if pingCheck { delay = float32(ms.Ping)/2000 + 0.06 + 0.03 + input.Delay } else { delay = input.Delay } wp := vector.GetFuturePoints(input.Unit) target_dir := vector.Normalize(input.Unit.AiManager.Velocity) if math.IsNaN(float64(target_dir.X)) { target_dir.X = 0.0 } if math.IsNaN(float64(target_dir.Y)) { target_dir.X = 0.0 } if math.IsNaN(float64(target_dir.Z)) { target_dir.X = 0.0 } if vector.DistanceBetweenTargets3D(input.Unit.Position, unitmanager.LOCALPLAYER.Position) > float64(input.Range) { return PredictionOutput{} } if !input.Unit.AiManager.IsMoving || len(wp) <= 1 || (target_dir.X == 0 && target_dir.Z == 0) { if checkCollision && vector.IsCollisioned(input.Unit, input.Unit.Position, input.Range) { return PredictionOutput{} } return PredictionOutput{CastPosition: input.Unit.Position} } if input.Unit.AiManager.IsDashing { if vector.Distance3D(input.Unit.AiManager.NavEnd, unitmanager.LOCALPLAYER.Position) >= float64(input.Range) { return PredictionOutput{} } return PredictionOutput{CastPosition: input.Unit.AiManager.NavEnd} } iterations := int(input.Range / 30.0) step := t_missile / float32(iterations) var last_dist = float64(9999999) var last_target_pos = unitmanager.GamePosition{} for i := 1; i <= iterations; i++ { t := float32(i) * step target_future_pos := vector.AddGamePosition(input.Unit.AiManager.ServerPos, vector.Scale(input.Unit.AiManager.MoveSpeed*(delay+t), target_dir)) spell_dir := vector.Scale(t*input.Speed, vector.Normalize(vector.SubGamePosition(target_future_pos, unitmanager.LOCALPLAYER.Position))) spell_future_pos := vector.AddGamePosition(unitmanager.LOCALPLAYER.Position, spell_dir) var dist = vector.Distance3D(target_future_pos, spell_future_pos) if dist < float64(input.Radius)/2.0 { return PredictionOutput{CastPosition: target_future_pos} } else if dist > float64(last_dist) { return PredictionOutput{CastPosition: last_target_pos} } else { last_dist = dist last_target_pos = target_future_pos } } return PredictionOutput{} }Editado pela última vez por magiok; Ontem às 02h30. Motivo: input.Unit.MovementSpeed em vez de input.Unit.AiManager.MoveSpeed
Fonte : https://www.unknowncheats.me/forum/league-of-legends/569781-prediction-league-legends-post3671687.html
![[Question] Previsão em League Of Legends](https://www.creocommunity.pt/wp-content/uploads/2023/02/Question-Previsao-em-League-Of-Legends.png)




