[Question] Previsão em League Of Legends


Venho tentando previsões diferentes há muito tempo, todas caem na mesma coisa e no final tudo acaba sendo altamente subjetivo.

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.pos

minha 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