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
}