Merge pull request #54 from superyu1337/development
Merge 'development' into 'main'
This commit is contained in:
		
							
								
								
									
										995
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										995
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										37
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | |||||||
| [package] | [package] | ||||||
| name = "radarflow" | name = "radarflow" | ||||||
| version = "0.2.4" | version = "0.2.5" | ||||||
| authors = ["Janek S <development@superyu.xyz"] | authors = ["Janek S <development@superyu.xyz"] | ||||||
| edition = "2021" | edition = "2021" | ||||||
|  |  | ||||||
| @@ -8,38 +8,39 @@ edition = "2021" | |||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
| # memory | # memory | ||||||
| memflow = "0.2.1" | memflow = "0.2.3" | ||||||
|  | memflow-native = { git = "https://github.com/memflow/memflow-native" } | ||||||
| dataview = "1.0.1" | dataview = "1.0.1" | ||||||
|  |  | ||||||
| # logging | # logging | ||||||
| log = "0.4.21" | log = "0.4.22" | ||||||
| simple_logger = "4.3.3" | simple_logger = "5.0.0" | ||||||
|  |  | ||||||
| # error handling | # error handling | ||||||
| anyhow = "1.0.81" | anyhow = "1.0.93" | ||||||
|  |  | ||||||
| # derive stuff | # derive stuff | ||||||
| enum-primitive-derive = "0.3.0" | enum-primitive-derive = "0.3.0" | ||||||
| num-traits = "0.2.18" | num-traits = "0.2.19" | ||||||
| serde = { version = "1.0.197", features = ["derive"] } | serde = { version = "1.0.215", features = ["derive"] } | ||||||
| serde_json = "1.0.115" | serde_json = "1.0.133" | ||||||
| clap = { version = "4.5.4", features = ["derive", "string"] } | clap = { version = "4.5.21", features = ["derive", "string"] } | ||||||
|  |  | ||||||
| # tokio | # tokio | ||||||
| tokio = { version = "1.37.0", features = ["full"] } | tokio = { version = "1.37.0", features = ["full"] } | ||||||
|  |  | ||||||
| # networking | # networking | ||||||
| axum = { version = "0.7.5", features = ["ws"] } | axum = { version = "0.7.9", features = ["ws"] } | ||||||
| tower-http = { version = "0.5.2", features = ["fs"] } | tower-http = { version = "0.6.2", features = ["fs"] } | ||||||
| tower = "0.4.13" | tower = "0.5.1" | ||||||
| local-ip-address = "0.6.1" | local-ip-address = "0.6.3" | ||||||
|  |  | ||||||
| # other | # other | ||||||
| itertools = "0.12.1" | itertools = "0.13.0" | ||||||
|  |  | ||||||
|  |  | ||||||
| [build-dependencies] | [build-dependencies] | ||||||
| reqwest = { version = "0.12.2", features = ["blocking"] } | reqwest = { version = "0.12.9", features = ["blocking"] } | ||||||
| serde = { version = "1.0.197", features = ["derive"] } | serde = { version = "1.0.215", features = ["derive"] } | ||||||
| serde_json = "1.0.115" | serde_json = "1.0.133" | ||||||
| vergen = { version = "8.3.1", features = ["build", "cargo", "git", "gitcl", "rustc", "si"] } | vergen-gitcl = { version = "1.0.0", features = ["build", "cargo", "rustc",] } | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								build.rs
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								build.rs
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | |||||||
| use std::error::Error; | use std::error::Error; | ||||||
|  |  | ||||||
| use serde::{Deserialize, Serialize}; | use serde::{Deserialize, Serialize}; | ||||||
| use vergen::EmitBuilder; | use vergen_gitcl::{Emitter, GitclBuilder}; | ||||||
|  |  | ||||||
| #[derive(Clone, Deserialize, Serialize)] | #[derive(Clone, Deserialize, Serialize)] | ||||||
| struct InfoJson { | struct InfoJson { | ||||||
| @@ -36,29 +36,27 @@ fn build_number() -> Result<(), Box<dyn Error>> { | |||||||
| fn main() -> Result<(), Box<dyn Error>> { | fn main() -> Result<(), Box<dyn Error>> { | ||||||
|  |  | ||||||
|     download( |     download( | ||||||
|         "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/client.dll.rs", |         "https://raw.githubusercontent.com/a2x/cs2-dumper/refs/heads/main/output/client_dll.rs", | ||||||
|         "./src/dma/cs2dumper/client_mod.rs" |         "./src/dma/cs2dumper/client_mod.rs" | ||||||
|     ).expect("Failed to download build file \"client.dll.rs\""); |     ).expect("Failed to download build file \"client.dll.rs\""); | ||||||
|  |  | ||||||
|     download( |     download( | ||||||
|         "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/offsets.rs", |         "https://raw.githubusercontent.com/a2x/cs2-dumper/refs/heads/main/output/offsets.rs", | ||||||
|         "./src/dma/cs2dumper/offsets_mod.rs" |         "./src/dma/cs2dumper/offsets_mod.rs" | ||||||
|     ).expect("Failed to download build file \"offsets.rs\""); |     ).expect("Failed to download build file \"offsets.rs\""); | ||||||
|  |  | ||||||
|     download( |     download( | ||||||
|         "https://raw.githubusercontent.com/a2x/cs2-dumper/main/output/engine2.dll.rs", |         "https://raw.githubusercontent.com/a2x/cs2-dumper/refs/heads/main/output/engine2_dll.rs", | ||||||
|         "./src/dma/cs2dumper/engine2_mod.rs" |         "./src/dma/cs2dumper/engine2_mod.rs" | ||||||
|     ).expect("Failed to download build file \"engine2.dll.rs\""); |     ).expect("Failed to download build file \"engine2.dll.rs\""); | ||||||
|  |  | ||||||
|     build_number()?; |     build_number()?; | ||||||
|  |  | ||||||
|     EmitBuilder::builder() |     let gitcl = GitclBuilder::all_git()?; | ||||||
|         .git_sha(true) |  | ||||||
|         .git_commit_date() |  | ||||||
|         .cargo_debug() |     Emitter::new() | ||||||
|         .cargo_target_triple() |         .add_instructions(&gitcl)? | ||||||
|         .rustc_semver() |  | ||||||
|         .rustc_llvm_version() |  | ||||||
|         .emit()?; |         .emit()?; | ||||||
|  |  | ||||||
|     Ok(()) |     Ok(()) | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								src/cli.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/cli.rs
									
									
									
									
									
								
							| @@ -40,10 +40,16 @@ fn version() -> String { | |||||||
|     let commit_date = option_env!("VERGEN_GIT_COMMIT_DATE").unwrap_or("unknown"); |     let commit_date = option_env!("VERGEN_GIT_COMMIT_DATE").unwrap_or("unknown"); | ||||||
|     let avail_cons = { |     let avail_cons = { | ||||||
|         let inventory = Inventory::scan(); |         let inventory = Inventory::scan(); | ||||||
|         inventory.available_connectors().join(", ") |         let mut avail = inventory.available_connectors(); | ||||||
|  |         avail.push("native".into()); | ||||||
|  |         avail.join(", ") | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     format!(" {pkg_ver} (rev {git_hash})\nCommit Date: {commit_date}\nAvailable Connectors: {avail_cons}") |     format!( | ||||||
|  |         "{pkg_ver} (rev {git_hash})\n\ | ||||||
|  |         Commit Date: {commit_date}\n\ | ||||||
|  |         Available Connectors: {avail_cons}\n" | ||||||
|  |     ) | ||||||
| } | } | ||||||
|  |  | ||||||
| fn port_in_range(s: &str) -> Result<u16, String> { | fn port_in_range(s: &str) -> Result<u16, String> { | ||||||
|   | |||||||
| @@ -3,7 +3,8 @@ pub enum Connector { | |||||||
|     #[default] |     #[default] | ||||||
|     Qemu, |     Qemu, | ||||||
|     Kvm, |     Kvm, | ||||||
|     Pcileech |     Pcileech, | ||||||
|  |     Native | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ToString for Connector { | impl ToString for Connector { | ||||||
| @@ -12,6 +13,7 @@ impl ToString for Connector { | |||||||
|             Connector::Qemu => String::from("qemu"), |             Connector::Qemu => String::from("qemu"), | ||||||
|             Connector::Kvm => String::from("kvm"), |             Connector::Kvm => String::from("kvm"), | ||||||
|             Connector::Pcileech => String::from("pcileech"), |             Connector::Pcileech => String::from("pcileech"), | ||||||
|  |             Connector::Native => String::from("native"), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ use num_traits::FromPrimitive; | |||||||
|  |  | ||||||
| use crate::{structs::Vec3, enums::TeamID}; | use crate::{structs::Vec3, enums::TeamID}; | ||||||
|  |  | ||||||
| use super::cs2dumper; | use super::{cs2dumper, threaddata::CsData}; | ||||||
|  |  | ||||||
| pub struct DmaCtx { | pub struct DmaCtx { | ||||||
|     pub process: IntoProcessInstanceArcBox<'static>, |     pub process: IntoProcessInstanceArcBox<'static>, | ||||||
| @@ -46,11 +46,13 @@ impl DmaCtx { | |||||||
|                     .args(connector_args) |                     .args(connector_args) | ||||||
|                     .os("win32") |                     .os("win32") | ||||||
|                     .build()? |                     .build()? | ||||||
|             } else { |             } else if connector != Connector::Native { | ||||||
|                 inventory.builder() |                 inventory.builder() | ||||||
|                 .connector(&connector.to_string()) |                     .connector(&connector.to_string()) | ||||||
|                 .os("win32") |                     .os("win32") | ||||||
|                 .build()? |                     .build()? | ||||||
|  |             } else { | ||||||
|  |                 memflow_native::create_os(&Default::default(), Default::default())? | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
| @@ -103,7 +105,7 @@ impl DmaCtx { | |||||||
|             batcher.read_into(pawn + cs2dumper::client::C_BaseEntity::m_iHealth, &mut health); |             batcher.read_into(pawn + cs2dumper::client::C_BaseEntity::m_iHealth, &mut health); | ||||||
|             batcher.read_into(controller + cs2dumper::client::C_BaseEntity::m_iTeamNum, &mut team); |             batcher.read_into(controller + cs2dumper::client::C_BaseEntity::m_iTeamNum, &mut team); | ||||||
|             batcher.read_into(pawn + cs2dumper::client::C_CSPlayerPawnBase::m_pClippingWeapon, &mut clipping_weapon); |             batcher.read_into(pawn + cs2dumper::client::C_CSPlayerPawnBase::m_pClippingWeapon, &mut clipping_weapon); | ||||||
|             batcher.read_into(pawn + cs2dumper::client::C_CSPlayerPawnBase::m_bIsScoped, &mut is_scoped); |             batcher.read_into(pawn + cs2dumper::client::C_CSPlayerPawn::m_bIsScoped, &mut is_scoped); | ||||||
|         } |         } | ||||||
|      |      | ||||||
|         let team = TeamID::from_i32(team); |         let team = TeamID::from_i32(team); | ||||||
| @@ -144,41 +146,101 @@ impl DmaCtx { | |||||||
|         Ok(is_controller) |         Ok(is_controller) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Todo: Optimize this function: find another way to do this |     pub fn get_c4_holder(&mut self, pawns: Vec<Address>, entity_list: Address, csdata: &CsData) -> Option<Address> { | ||||||
|     pub fn has_c4(&mut self, pawn: Address, entity_list: Address) -> anyhow::Result<bool> { |  | ||||||
|         let mut has_c4 = false; |  | ||||||
|         let wep_services = self.process.read_addr64(pawn + cs2dumper::client::C_BasePlayerPawn::m_pWeaponServices)?; |  | ||||||
|         let wep_count: i32  = self.process.read(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons)?; |  | ||||||
|         let wep_base = self.process.read_addr64(wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons + 0x8)?; |  | ||||||
|  |  | ||||||
|         for wep_idx in 0..wep_count { |         if csdata.bomb_dropped || csdata.bomb_planted { | ||||||
|             let handle: i32 = self.process.read(wep_base + wep_idx * 0x4)?; |             return None; | ||||||
|             if handle == -1 { |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             let list_entry = self.process.read_addr64(entity_list + 0x8 * ((handle & 0x7FFF) >> 9) + 16)?; |  | ||||||
|             if let Some(wep_ptr) = { |  | ||||||
|                 if list_entry.is_null() || !list_entry.is_valid() { |  | ||||||
|                     None |  | ||||||
|                 } else { |  | ||||||
|                     let ptr = self.process.read_addr64(list_entry + 120 * (handle & 0x1FF))?; |  | ||||||
|                     Some(ptr) |  | ||||||
|                 } |  | ||||||
|             } { |  | ||||||
|                 let wep_data = self.process.read_addr64(wep_ptr + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8)?; |  | ||||||
|                 let id: i32 = self.process.read(wep_data + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType)?; |  | ||||||
|  |  | ||||||
|                 if id == 7 { |  | ||||||
|                     has_c4 = true; |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Ok(has_c4) |         // (pawn, wep_services, wep_count, wep_base) | ||||||
|     } |         let mut data_vec: Vec<(Address, u64, i32, u64)> = pawns | ||||||
|  |             .into_iter() | ||||||
|  |             .map(|pawn| (pawn, 0u64, 0i32, 0u64)) | ||||||
|  |             .collect(); | ||||||
|  |  | ||||||
|  |         // Get wep_services | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(pawn, wep_services, _, _)| { | ||||||
|  |             batcher.read_into(*pawn + cs2dumper::client::C_BasePlayerPawn::m_pWeaponServices, wep_services); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Get wep_count and wep_base | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, wep_services, wep_count, wep_base)| { | ||||||
|  |             batcher.read_into((*wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons as u64).into(), wep_count); | ||||||
|  |             batcher.read_into((*wep_services + cs2dumper::client::CPlayer_WeaponServices::m_hMyWeapons as u64 + 0x8).into() , wep_base); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Rebuild data vec | ||||||
|  |         // Vec<(pawn, wep_base, Vec<(buff, buff2)>)> | ||||||
|  |         let mut data_vec: Vec<(Address, u64, Vec<(u64, i32)>)> = data_vec | ||||||
|  |             .into_iter() | ||||||
|  |             .map(|(pawn, _, wep_count, wep_base)| { | ||||||
|  |                 let weps = (0..wep_count).into_iter().map(|idx| (0u64, idx)).collect(); | ||||||
|  |                 (pawn, wep_base, weps) | ||||||
|  |             }) | ||||||
|  |             .collect(); | ||||||
|  |  | ||||||
|  |         // Get handle | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, wep_base, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter_mut().for_each(|(_, idx)| { | ||||||
|  |                 let b: Address = (*wep_base).into(); | ||||||
|  |                 batcher.read_into(b + * idx * 0x4, idx); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Get list entry | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter_mut().for_each(|(list_entry, handle)| { | ||||||
|  |                 batcher.read_into(entity_list + 0x8 * ((*handle & 0x7FFF) >> 9) + 16, list_entry); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Get wep ptr | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter_mut().for_each(|(list_entry, handle)| { | ||||||
|  |                 let le: Address = (*list_entry).into(); | ||||||
|  |                 batcher.read_into(le + 120 * (*handle & 0x1FF), list_entry); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Get wep data | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter_mut().for_each(|(wep_ptr, _)| { | ||||||
|  |                 let b: Address = (*wep_ptr).into(); | ||||||
|  |                 batcher.read_into(b + cs2dumper::client::C_BaseEntity::m_nSubclassID + 0x8, wep_ptr); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         // Get wep id | ||||||
|  |         let mut batcher = self.process.batcher(); | ||||||
|  |         data_vec.iter_mut().for_each(|(_, _, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter_mut().for_each(|(wep_data, id)| { | ||||||
|  |                 let b: Address = (*wep_data).into(); | ||||||
|  |                 batcher.read_into(b + cs2dumper::client::CCSWeaponBaseVData::m_WeaponType, id); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |         drop(batcher); | ||||||
|  |  | ||||||
|  |         let holder = data_vec.into_iter().find(|(_, _, wep_data_vec)| { | ||||||
|  |             wep_data_vec.iter().find(|(_, id)| { *id == 7 }).is_some() | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         match holder { | ||||||
|  |             Some((addr, _, _)) => Some(addr), | ||||||
|  |             None => None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| use std::{thread, time::{Duration, Instant}}; | use std::{thread, time::{Duration, Instant}}; | ||||||
|  |  | ||||||
| use memflow::{os::Process, types::Address, mem::MemoryView}; | use memflow::{mem::MemoryView, os::Process, types::Address}; | ||||||
|  |  | ||||||
| use crate::{enums::{TeamID, PlayerType}, comms::{EntityData, PlayerData, RadarData, ArcRwlockRadarData, BombData}}; | use crate::{enums::PlayerType, comms::{EntityData, PlayerData, RadarData, ArcRwlockRadarData, BombData}}; | ||||||
|  |  | ||||||
| use self::{context::DmaCtx, threaddata::CsData}; | use self::{context::DmaCtx, threaddata::CsData}; | ||||||
|  |  | ||||||
| @@ -19,6 +19,8 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ | |||||||
|     // For read timing |     // For read timing | ||||||
|     let mut last_bomb_dropped = false; |     let mut last_bomb_dropped = false; | ||||||
|     let mut last_bomb_planted = false; |     let mut last_bomb_planted = false; | ||||||
|  |     let mut last_freeze_period = false; | ||||||
|  |     let mut last_round_start_count = 0u8; | ||||||
|     let mut last_tick_count = 0; |     let mut last_tick_count = 0; | ||||||
|     let mut last_big_read = Instant::now(); |     let mut last_big_read = Instant::now(); | ||||||
|  |  | ||||||
| @@ -50,10 +52,37 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ | |||||||
|             data.update_bomb(&mut ctx); |             data.update_bomb(&mut ctx); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if !data.bomb_dropped && last_bomb_dropped && !data.bomb_planted { |         if data.bomb_dropped != last_bomb_dropped || data.bomb_planted != last_bomb_planted { | ||||||
|  |             log::debug!("Bomb holder recheck due to bomb status"); | ||||||
|             data.recheck_bomb_holder = true; |             data.recheck_bomb_holder = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if last_freeze_period != data.freeze_period { | ||||||
|  |             log::debug!("Bomb holder recheck due to freeze time"); | ||||||
|  |             data.recheck_bomb_holder = true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if last_round_start_count != data.round_start_count { | ||||||
|  |             log::debug!("Bomb holder recheck due to round start"); | ||||||
|  |             data.recheck_bomb_holder = true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         last_freeze_period = data.freeze_period; | ||||||
|  |         last_round_start_count = data.round_start_count; | ||||||
|  |  | ||||||
|  |         if data.recheck_bomb_holder { | ||||||
|  |             let mut pawns: Vec<Address> = data.players | ||||||
|  |                 .clone() | ||||||
|  |                 .into_iter() | ||||||
|  |                 .map(|(_, pawn)| pawn) | ||||||
|  |                 .collect(); | ||||||
|  |  | ||||||
|  |             pawns.push(data.local_pawn.into()); | ||||||
|  |          | ||||||
|  |             data.bomb_holder = ctx.get_c4_holder(pawns, data.entity_list.into(), &data); | ||||||
|  |             data.recheck_bomb_holder = false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         let bomb_defuse_timeleft: f32 = { |         let bomb_defuse_timeleft: f32 = { | ||||||
|             if data.bomb_planted && !data.bomb_exploded && !data.bomb_defused { |             if data.bomb_planted && !data.bomb_exploded && !data.bomb_defused { | ||||||
|                 if let Some(bomb_stamp) = data.bomb_planted_stamp { |                 if let Some(bomb_stamp) = data.bomb_planted_stamp { | ||||||
| @@ -123,23 +152,9 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ | |||||||
|             ).unwrap(); |             ).unwrap(); | ||||||
|  |  | ||||||
|             if local_data.health > 0 { |             if local_data.health > 0 { | ||||||
|                 let has_bomb = { |                 let has_bomb = match data.bomb_holder { | ||||||
|                     if data.bomb_planted || data.bomb_dropped { |                     Some(bh) => data.local_pawn == bh.to_umem(), | ||||||
|                         false |                     None => false, | ||||||
|                     } else if data.recheck_bomb_holder { |  | ||||||
|                         if local_data.team == Some(TeamID::T) && !data.bomb_dropped && !data.bomb_planted { |  | ||||||
|                             let is_holder = ctx.has_c4( |  | ||||||
|                                 data.local_pawn.into(), data.entity_list.into() |  | ||||||
|                             ).unwrap_or(false); |  | ||||||
|  |  | ||||||
|                             if is_holder { |  | ||||||
|                                 data.bomb_holder = data.local.into(); |  | ||||||
|                                 data.recheck_bomb_holder = false; |  | ||||||
|                             } |  | ||||||
|  |  | ||||||
|                             is_holder |  | ||||||
|                         } else { false } |  | ||||||
|                     } else { Address::from(data.local) == data.bomb_holder } |  | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 entity_data.push( |                 entity_data.push( | ||||||
| @@ -164,21 +179,9 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_ | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 let has_bomb = { |                 let has_bomb = match data.bomb_holder { | ||||||
|                     if data.bomb_planted { |                     Some(bh) => *pawn == bh, | ||||||
|                         false |                     None => false, | ||||||
|                     } else if data.recheck_bomb_holder { |  | ||||||
|                         if player_data.team == Some(TeamID::T) && !data.bomb_dropped && !data.bomb_planted { |  | ||||||
|                             let is_holder = ctx.has_c4(*pawn, data.entity_list.into()).unwrap_or(false); |  | ||||||
|  |  | ||||||
|                             if is_holder { |  | ||||||
|                                 data.bomb_holder = *controller; |  | ||||||
|                                 data.recheck_bomb_holder = false; |  | ||||||
|                             } |  | ||||||
|  |  | ||||||
|                             is_holder |  | ||||||
|                         } else { false } |  | ||||||
|                     } else { *controller == data.bomb_holder } |  | ||||||
|                 }; |                 }; | ||||||
|  |  | ||||||
|                 let player_type = { |                 let player_type = { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ pub struct CsData { | |||||||
|     // Entities |     // Entities | ||||||
|     pub players: Vec<(Address, Address)>, |     pub players: Vec<(Address, Address)>, | ||||||
|     pub bomb: Address, |     pub bomb: Address, | ||||||
|     pub bomb_holder: Address, |     pub bomb_holder: Option<Address>, | ||||||
|     pub recheck_bomb_holder: bool, |     pub recheck_bomb_holder: bool, | ||||||
|  |  | ||||||
|     // Pointers |     // Pointers | ||||||
| @@ -21,8 +21,14 @@ pub struct CsData { | |||||||
|     // Common |     // Common | ||||||
|     pub local: u64, |     pub local: u64, | ||||||
|     pub local_pawn: u64, |     pub local_pawn: u64, | ||||||
|     pub is_dead: bool, |     // pub is_dead: bool,   // TODO: Why is this here? | ||||||
|     pub tick_count: i32, |     pub tick_count: i32, | ||||||
|  |     pub freeze_period: bool, | ||||||
|  |     pub round_start_count: u8, | ||||||
|  |     pub highest_index: i32, | ||||||
|  |     pub map: String, | ||||||
|  |  | ||||||
|  |     // Bomb | ||||||
|     pub bomb_dropped: bool, |     pub bomb_dropped: bool, | ||||||
|     pub bomb_planted: bool, |     pub bomb_planted: bool, | ||||||
|     pub bomb_planted_stamp: Option<Instant>, |     pub bomb_planted_stamp: Option<Instant>, | ||||||
| @@ -32,8 +38,6 @@ pub struct CsData { | |||||||
|     pub bomb_defuse_length: f32, |     pub bomb_defuse_length: f32, | ||||||
|     pub bomb_exploded: bool, |     pub bomb_exploded: bool, | ||||||
|     pub bomb_defused: bool, |     pub bomb_defused: bool, | ||||||
|     pub highest_index: i32, |  | ||||||
|     pub map: String |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -161,7 +165,7 @@ impl CsData { | |||||||
|         let mut bomb_being_defused = 0u8; |         let mut bomb_being_defused = 0u8; | ||||||
|         let mut bomb_exploded = 0u8; |         let mut bomb_exploded = 0u8; | ||||||
|         let mut bomb_defused = 0u8; |         let mut bomb_defused = 0u8; | ||||||
|  |         let mut freeze_period = 0u8; | ||||||
|         { |         { | ||||||
|             // Globals |             // Globals | ||||||
|             let tick_count_addr = (self.globals + 0x40).into(); |             let tick_count_addr = (self.globals + 0x40).into(); | ||||||
| @@ -170,9 +174,11 @@ impl CsData { | |||||||
|             // Gamerules |             // Gamerules | ||||||
|             let bomb_dropped_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_bBombDropped as u64).into(); |             let bomb_dropped_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_bBombDropped as u64).into(); | ||||||
|             let bomb_planted_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_bBombPlanted as u64).into(); |             let bomb_planted_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_bBombPlanted as u64).into(); | ||||||
|  |             let total_rounds_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_bFreezePeriod as u64).into(); | ||||||
|  |             let round_start_count_addr = (self.gamerules + cs2dumper::client::C_CSGameRules::m_nRoundStartCount as u64).into(); | ||||||
|  |  | ||||||
|             // Game Entity System |             // Game Entity System | ||||||
|             let highest_index_addr = (self.game_ent_sys + cs2dumper::offsets::client_dll::dwGameEntitySystem_getHighestEntityIndex as u64).into(); |             let highest_index_addr = (self.game_ent_sys + cs2dumper::offsets::client_dll::dwGameEntitySystem_highestEntityIndex as u64).into(); | ||||||
|  |  | ||||||
|             let mut batcher = ctx.process.batcher(); |             let mut batcher = ctx.process.batcher(); | ||||||
|             batcher.read_into( |             batcher.read_into( | ||||||
| @@ -187,6 +193,8 @@ impl CsData { | |||||||
|             batcher.read_into(tick_count_addr, &mut self.tick_count); |             batcher.read_into(tick_count_addr, &mut self.tick_count); | ||||||
|             batcher.read_into(bomb_dropped_addr, &mut bomb_dropped); |             batcher.read_into(bomb_dropped_addr, &mut bomb_dropped); | ||||||
|             batcher.read_into(bomb_planted_addr, &mut bomb_planted); |             batcher.read_into(bomb_planted_addr, &mut bomb_planted); | ||||||
|  |             batcher.read_into(total_rounds_addr, &mut freeze_period); | ||||||
|  |             batcher.read_into(round_start_count_addr, &mut self.round_start_count); | ||||||
|             batcher.read_into(highest_index_addr, &mut self.highest_index); |             batcher.read_into(highest_index_addr, &mut self.highest_index); | ||||||
|             batcher.read_into(map_addr, &mut map_ptr); |             batcher.read_into(map_addr, &mut map_ptr); | ||||||
|         } |         } | ||||||
| @@ -229,7 +237,7 @@ impl CsData { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
|         let map_string = ctx.process.read_char_string_n(map_ptr.into(), 32).unwrap_or(String::from("<empty>")); |         let map_string = ctx.process.read_utf8_lossy(map_ptr.into(), 32).unwrap_or(String::from("<empty>")); | ||||||
|  |  | ||||||
|         self.map = map_string; |         self.map = map_string; | ||||||
|         self.bomb_dropped = bomb_dropped != 0; |         self.bomb_dropped = bomb_dropped != 0; | ||||||
| @@ -237,6 +245,7 @@ impl CsData { | |||||||
|         self.bomb_exploded = bomb_exploded != 0; |         self.bomb_exploded = bomb_exploded != 0; | ||||||
|         self.bomb_being_defused = bomb_being_defused != 0; |         self.bomb_being_defused = bomb_being_defused != 0; | ||||||
|         self.bomb_defused = bomb_defused != 0; |         self.bomb_defused = bomb_defused != 0; | ||||||
|  |         self.freeze_period = freeze_period != 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     pub fn update_pointers(&mut self, ctx: &mut DmaCtx) { |     pub fn update_pointers(&mut self, ctx: &mut DmaCtx) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user