nezha/src/pokemmo/pokemmo.rs

233 lines
9.6 KiB
Rust
Raw Normal View History

2023-08-01 00:19:05 +08:00
#[cfg(feature = "pokemmo")]
2023-08-22 00:01:59 +08:00
pub mod pokemmo {
use std::thread;
use std::time::Duration;
use enigo::Key;
use enigo::Key::{N, V};
use image::{DynamicImage, RgbaImage};
2023-08-01 00:19:05 +08:00
use image::io::Reader as ImageReader;
2023-08-22 00:01:59 +08:00
use log::{error, info, trace};
use rand::thread_rng;
use rusty_tesseract::Image;
use screenshots::Compression;
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
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};
2024-01-05 00:39:17 +08:00
use crate::pokemmo::const_value::pokemmo_const_value::PokemmoStatus::{Free, InBattle, LoadBattle, MeetTarget, Running};
2023-08-22 00:01:59 +08:00
use crate::screen::screen::screen::{Area, screen_shot};
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
// 单遇闪光
pub fn single_meet_shiny(key_words: &Vec<String>) {
let mut status = PokemmoStatus::Free;
let move_mode = MoveMode::HORIZONTAL;
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
let mut move_index = 0_usize;
let mut meet_pokemmo: String = String::new();
loop {
trace!("当前状态:{:?}",status);
match status {
2024-01-05 00:39:17 +08:00
PokemmoStatus::MeetTarget => {
2023-08-22 00:01:59 +08:00
return;
}
PokemmoStatus::Free => {
trace!("自由状态,移动一步");
move_once_by_mode(&move_mode, move_index);
move_index = move_index + 1;
let text = get_last_string();
trace!("查询战斗文字 : {}",text);
2024-01-05 00:39:17 +08:00
if text.contains("wild") || text.contains("sent") {
2023-08-22 00:01:59 +08:00
info!("遇怪:{}.",text);
meet_pokemmo = text.clone();
status = LoadBattle;
}else {
let temp_battle = read_area(TEMP_BATTLE_TEXT_AREA);
2024-01-05 00:39:17 +08:00
if temp_battle.contains("fight") || temp_battle.contains("run"){
2023-08-22 00:01:59 +08:00
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();
2024-01-05 00:39:17 +08:00
let filter_text: Vec<String> = text.into_iter().filter(|x| x.contains("wild")).collect();
2023-08-22 00:01:59 +08:00
if filter_text.is_empty() {
error!("遇怪错误!");
return;
}
let filter_size = filter_text.len();
let pokemon_text = filter_text[filter_size - 1].clone();
2024-01-05 00:39:17 +08:00
if pokemon_text.contains("horde") {
2023-08-22 00:01:59 +08:00
info!("遇见怪群");
let five_names = read_group_5();
for name in five_names {
for key_word in key_words {
if name.contains(key_word) {
2024-01-05 00:39:17 +08:00
status = MeetTarget;
2023-08-22 00:01:59 +08:00
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);
2024-01-05 00:39:17 +08:00
status = MeetTarget;
2023-08-22 00:01:59 +08:00
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;
2024-01-05 00:39:17 +08:00
while !last_word.contains("escaped")
2023-08-22 00:01:59 +08:00
&& !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;
}
2024-01-05 00:39:17 +08:00
if last_word.contains("escaped") || last_word.contains("safely") {
2023-08-22 00:01:59 +08:00
trace!("逃跑成功.");
status = Free;
} else {
trace!("逃跑失败");
status = Free;
}
}
}
}
}
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
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;
}
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
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");
2023-08-01 00:19:05 +08:00
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;
2023-08-22 00:01:59 +08:00
for i in 0..size {
dis += active_logo_data[i.clone()].clone() as isize - data[i].clone() as isize;
2023-08-01 00:19:05 +08:00
}
2023-08-22 00:01:59 +08:00
println!("dis : {}", dis);
2023-08-01 00:19:05 +08:00
return dis <= 5000;
2023-08-22 00:01:59 +08:00
}
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());
2024-01-05 00:39:17 +08:00
let text = find_string_in_image(&dy_image, psm).to_lowercase();
2023-08-22 00:01:59 +08:00
return text;
}
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
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;
2023-08-01 00:19:05 +08:00
}
2023-08-22 00:01:59 +08:00
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;
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
let r1 = r_avg as f32 / 255_f32;
let g1 = g_avg as f32 / 255_f32;
let b1 = b_avg as f32 / 255_f32;
2023-08-01 00:19:05 +08:00
2023-08-22 00:01:59 +08:00
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;
}
2023-08-01 00:19:05 +08:00
}