1- use std:: { ffi :: c_void , mem , ptr} ;
1+ use std:: { mem , ops :: Deref , ptr} ;
22
3- use log:: debug ;
3+ use log:: warn ;
44
5- use crate :: { data:: p3_ptr:: P3Pointer , Point } ;
5+ use crate :: {
6+ data:: {
7+ enums:: { ShipType , TownId } ,
8+ p3_ptr:: P3Pointer ,
9+ } ,
10+ town:: static_town_data:: StaticTownDataPtr ,
11+ Point ,
12+ } ;
613
714const CLASS35_PTR_ADDRESS : * const u32 = 0x006CBDC8 as _ ;
15+ pub const CAPACITY_FACTOR_MAX : u32 = 4096 ;
16+ pub const HEALTH_FACTOR_MAX : u32 = 256 ;
817
9- #[ derive( Clone , Debug ) ]
18+ #[ derive( Clone , Debug , Copy ) ]
1019pub struct Class35Ptr {
1120 pub address : u32 ,
1221}
1322
23+ #[ derive( Clone , Debug ) ]
24+ pub struct ShipRoutePtr {
25+ pub address : u32 ,
26+ pub needs_free : bool ,
27+ }
28+
29+ impl ShipRoutePtr {
30+ pub unsafe fn calculate_distance ( & self ) -> i32 {
31+ let mut distance = 0 ;
32+ if self . len > 1 {
33+ for i in 1 ..self . len as usize {
34+ let p0 = ( * self . points . add ( i - 1 ) ) . clone ( ) ;
35+ let p1 = ( * self . points . add ( i) ) . clone ( ) ;
36+ let x_diff = ( p0. x - p1. x ) . abs ( ) ;
37+ let y_diff = ( p0. y - p1. y ) . abs ( ) ;
38+ if x_diff <= y_diff {
39+ distance += ( 16 * y_diff + 7 * x_diff) as i32 ;
40+ } else {
41+ distance += ( 16 * x_diff + 7 * y_diff) as i32 ;
42+ }
43+ }
44+ }
45+
46+ distance
47+ }
48+
49+ pub unsafe fn calculate_travel_time ( & self , ship_type : ShipType , health_factor : u32 , capacity_factor : u32 ) -> u32 {
50+ let capacity_scaled_speed = ( ship_type. get_base_speed ( ) as u32 * capacity_factor) >> 12 ;
51+ let speed_factor = ( capacity_scaled_speed * health_factor) >> 10 ;
52+ 8 * self . calculate_distance ( ) as u32 / speed_factor
53+ }
54+
55+ pub unsafe fn free ( self ) {
56+ if !self . needs_free {
57+ return ;
58+ }
59+ if !self . points . is_null ( ) {
60+ crate :: free ( self . points as usize as _ ) ;
61+ }
62+ crate :: free ( self . address ) ;
63+ }
64+ }
65+
66+ impl Deref for ShipRoutePtr {
67+ type Target = ShipRoute ;
68+
69+ fn deref ( & self ) -> & Self :: Target {
70+ unsafe { & * ( self . address as * const ShipRoute ) }
71+ }
72+ }
73+
1474#[ derive( Clone , Debug ) ]
1575#[ repr( C ) ]
1676pub struct ShipRoute {
17- pub points : * const c_void ,
77+ pub points : * mut Point < i16 > ,
1878 pub len : i32 ,
1979}
2080
@@ -37,18 +97,33 @@ impl Class35Ptr {
3797 Self { address : * CLASS35_PTR_ADDRESS }
3898 }
3999
40- pub unsafe fn calculate_ship_route ( & self , source : Point < i16 > , destination : Point < i16 > ) -> * const ShipRoute {
41- let args_inner = ShipRouteArgsInner { source, destination } ;
100+ pub unsafe fn calculate_town_route ( & self , source : TownId , destination : TownId ) -> Option < ShipRoutePtr > {
101+ let source_data = StaticTownDataPtr :: new ( source) ;
102+ let destination_data = StaticTownDataPtr :: new ( destination) ;
103+ self . calculate_route ( & source_data. get_point_i16 ( ) , & destination_data. get_point_i16 ( ) )
104+ }
105+
106+ pub unsafe fn calculate_route ( & self , source : & Point < i16 > , destination : & Point < i16 > ) -> Option < ShipRoutePtr > {
107+ let args_inner = ShipRouteArgsInner {
108+ source : source. clone ( ) ,
109+ destination : destination. clone ( ) ,
110+ } ;
42111 let args = ShipRouteArgs {
43112 args_inner : & args_inner,
44113 route_type : 2 ,
45114 } ;
46- let mut ship_route: * const ShipRoute = ptr:: null_mut ( ) ;
47- debug ! ( "Calling calculate_ship_route orig" ) ;
48- let orig: extern "thiscall" fn ( this : u32 , route_args : * const ShipRouteArgs , route : * mut * const ShipRoute ) -> i32 = mem:: transmute ( 0x00445010 ) ;
49- orig ( self . address , & args, & mut ship_route) ;
50- debug ! ( "Calling calculate_ship_route survived! {ship_route:?}" ) ;
51- ship_route
115+ let mut ship_route: * mut ShipRoute = ptr:: null_mut ( ) ;
116+ let orig: extern "thiscall" fn ( this : u32 , route_args : * const ShipRouteArgs , route : * mut * mut ShipRoute ) -> bool = mem:: transmute ( 0x00445010 ) ;
117+ let needs_free = orig ( self . address , & args, & mut ship_route) ;
118+ if !ship_route. is_null ( ) {
119+ Some ( ShipRoutePtr {
120+ address : ship_route as _ ,
121+ needs_free,
122+ } )
123+ } else {
124+ warn ! ( "Failed to calculate route {:x}" , ship_route as u32 ) ;
125+ None
126+ }
52127 }
53128}
54129
0 commit comments