#[cfg(feature = "pokemmo")] pub mod pokemmo { use std::thread; use std::time::Duration; use enigo::Key; use enigo::Key::{N, V}; use image::{DynamicImage, RgbaImage}; use image::io::Reader as ImageReader; use log::{error, info, trace}; use rand::thread_rng; use rusty_tesseract::Image; use screenshots::Compression; use crate::joystick::joystick::joystick::{move_once_by_mode, MoveMode, quick_press}; use crate::ocr::ocr::ocr::find_string_in_image; use crate::pokemmo::const_value::pokemmo_const_value::{BUTTON_HL_1, BUTTON_HL_2, BUTTON_HL_3, BUTTON_HL_4, GROUP_5_1, GROUP_5_2, GROUP_5_3, GROUP_5_4, GROUP_5_5, LAST_TEXT_AREA, LOGO, PokemmoStatus, SINGLE_BATTLE, TEMP_BATTLE_TEXT_AREA, TEXT_AREA}; use crate::pokemmo::const_value::pokemmo_const_value::PokemmoStatus::{Free, InBattle, LoadBattle, MeetTarget, Running}; use crate::screen::screen::screen::{Area, screen_shot}; // 单遇闪光 pub fn single_meet_shiny(key_words: &Vec) { let mut status = PokemmoStatus::Free; let move_mode = MoveMode::HORIZONTAL; let mut move_index = 0_usize; let mut meet_pokemmo: String = String::new(); loop { trace!("当前状态:{:?}",status); match status { PokemmoStatus::MeetTarget => { return; } PokemmoStatus::Free => { trace!("自由状态,移动一步"); move_once_by_mode(&move_mode, move_index); move_index = move_index + 1; let text = get_last_string(); trace!("查询战斗文字 : {}",text); if text.contains("wild") || text.contains("sent") { info!("遇怪:{}.",text); meet_pokemmo = text.clone(); status = LoadBattle; }else { let temp_battle = read_area(TEMP_BATTLE_TEXT_AREA); if temp_battle.contains("fight") || temp_battle.contains("run"){ status = LoadBattle; } } } PokemmoStatus::LoadBattle => { info!("进入加载动画"); let mut btn_index = None; while btn_index == None { trace!("等待按钮加载"); let est_index = get_choose_btn(); if est_index.is_some() { btn_index = est_index; status = InBattle; } thread::sleep(Duration::from_millis(100)); } } PokemmoStatus::InBattle => { trace!("检查遇怪种类.."); let text = get_text_list(); let filter_text: Vec = text.into_iter().filter(|x| x.contains("wild")).collect(); if filter_text.is_empty() { error!("遇怪错误!"); return; } let filter_size = filter_text.len(); let pokemon_text = filter_text[filter_size - 1].clone(); if pokemon_text.contains("horde") { info!("遇见怪群"); let five_names = read_group_5(); for name in five_names { for key_word in key_words { if name.contains(key_word) { status = MeetTarget; return; } } } } else { let name = read_area(SINGLE_BATTLE); info!("单遇:{}",name); for key_word in key_words { if name.contains(key_word) || meet_pokemmo.contains(key_word) { info!("遇见{}",key_word); status = MeetTarget; return; } } } // 进入招式界面 status = PokemmoStatus::Running } PokemmoStatus::Running => { thread::sleep(Duration::from_micros(100)); quick_press(Key::Layout('l')); thread::sleep(Duration::from_micros(100)); quick_press(Key::Layout('k')); thread::sleep(Duration::from_micros(100)); let mut est_index = get_choose_btn(); while est_index.is_none() || est_index.unwrap() != 3 { quick_press(Key::Layout('l')); quick_press(Key::Layout('k')); trace!("尝试获取激活按钮"); est_index = get_choose_btn(); } quick_press(Key::Layout('z')); thread::sleep(Duration::from_micros(100)); status = PokemmoStatus::CheckRun; } PokemmoStatus::CheckRun => { let mut last_word = get_last_string(); // 读取十次后默认成功 let mut times = 0_usize; while !last_word.contains("escaped") && !last_word.contains("中逃跑") && !last_word.contains("不能跑") && times < 10{ trace!("读取逃跑文档 : {}",last_word); last_word = get_last_string(); thread::sleep(Duration::from_millis(200)); times = times + 1; } if last_word.contains("escaped") || last_word.contains("safely") { trace!("逃跑成功."); status = Free; } else { trace!("逃跑失败"); status = Free; } } } } } pub fn get_text_list() -> Vec { let text_image = read_area(TEXT_AREA); let text_list: Vec = text_image.split("\r\n").filter(|x| !x.is_empty()).map(|x| String::from(x)).collect(); return text_list; } pub fn get_last_string() -> String { let text_image = read_area(LAST_TEXT_AREA); return text_image; } pub(crate) fn check_screen_active() -> bool { let logo_image = screen_shot(Some(LOGO)); let data = logo_image.to_png(Some(Compression::Default)).expect("image to png failed"); let active_logo = ImageReader::open("./resources/pokemmo/image/logo_active.png").expect("read active logo image failed").decode().expect("decode image failed"); let active_logo_data = active_logo.as_bytes().to_vec(); let size = data.len(); let mut dis = 0_isize; for i in 0..size { dis += active_logo_data[i.clone()].clone() as isize - data[i].clone() as isize; } println!("dis : {}", dis); return dis <= 5000; } pub fn read_area(area: Area) -> String { let psm = area.psm.clone(); let image = screen_shot(Some(area)); let image_data = image.rgba().clone(); let image_width = image.width(); let image_height = image.height(); let dy_image = DynamicImage::from(RgbaImage::from_vec(image_width, image_height, image_data).unwrap()); let text = find_string_in_image(&dy_image, psm).to_lowercase(); return text; } pub fn read_group_5() -> Vec { let mut result = Vec::new(); result.push(read_area(GROUP_5_1)); result.push(read_area(GROUP_5_2)); result.push(read_area(GROUP_5_3)); result.push(read_area(GROUP_5_4)); result.push(read_area(GROUP_5_5)); return result; } pub fn get_choose_btn() -> Option { let mut btn_list = Vec::new(); btn_list.push(screen_shot(Some(BUTTON_HL_1))); btn_list.push(screen_shot(Some(BUTTON_HL_2))); btn_list.push(screen_shot(Some(BUTTON_HL_3))); btn_list.push(screen_shot(Some(BUTTON_HL_4))); let mut y_max = 0_f32; let mut max_index = None; for index in 0..4 { let image = &mut btn_list[index]; let data = image.rgba(); let size = data.len(); let pixel_size = size / 4; let mut r_total = 0_usize; let mut g_total = 0_usize; let mut b_total = 0_usize; for i in 0..pixel_size { r_total += (data[i.clone() * 4].clone() as usize); g_total += (data[i.clone() * 4 + 1].clone() as usize); b_total += (data[i.clone() * 4 + 2].clone() as usize); } let r_avg = r_total / pixel_size; let g_avg = g_total / pixel_size; let b_avg = b_total / pixel_size; let r1 = r_avg as f32 / 255_f32; let g1 = g_avg as f32 / 255_f32; let b1 = b_avg as f32 / 255_f32; let max = r1.max(g1).max(b1); let k = 1_f32 - max; let y = (1_f32 - b1 - k) / (1_f32 - k); if y > y_max && y > 0.4_f32 { y_max = y; max_index = Some(index); } } return max_index; } }