233 lines
9.6 KiB
Rust
233 lines
9.6 KiB
Rust
#[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<String>) {
|
||
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<String> = 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<String> {
|
||
let text_image = read_area(TEXT_AREA);
|
||
let text_list: Vec<String> = 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<String> {
|
||
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<usize> {
|
||
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;
|
||
}
|
||
} |