use crate::defines::LevelInt; use crate::dynamic_data::{Battle, DamageSource, DynamicLibrary, LearnedMove, MoveLearnMethod, Pokemon}; use crate::ffi::{ffi_arc_getter, ffi_vec_value_getters, ExternPointer, IdentifiablePointer, OwnedPtr}; use crate::static_data::{ Ability, AbilityIndex, Form, Gender, Item, Nature, Species, Statistic, StatisticSet, TypeIdentifier, }; use std::ffi::{c_char, CStr, CString}; use std::ptr::drop_in_place; use std::sync::Arc; #[no_mangle] extern "C" fn pokemon_new( library: ExternPointer>, species: ExternPointer>, form: ExternPointer>, hidden_ability: bool, ability_index: u8, level: LevelInt, unique_identifier: u32, gender: Gender, coloring: u8, nature: *const c_char, ) -> IdentifiablePointer> { let nature = unsafe { CStr::from_ptr(nature) }.into(); Arc::new(Pokemon::new( library.as_ref().clone(), species.as_ref().clone(), form.as_ref(), AbilityIndex { hidden: hidden_ability, index: ability_index, }, level, unique_identifier, gender, coloring, &nature, )) .into() } #[no_mangle] unsafe extern "C" fn pokemon_drop(ptr: OwnedPtr>) { drop_in_place(ptr); } #[no_mangle] extern "C" fn pokemon_library(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().library().clone().into() } #[no_mangle] extern "C" fn pokemon_species(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().species().clone().into() } #[no_mangle] extern "C" fn pokemon_form(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().form().clone().into() } #[no_mangle] extern "C" fn pokemon_display_species(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().display_species().clone().into() } #[no_mangle] extern "C" fn pokemon_display_form(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().display_form().clone().into() } ffi_arc_getter!(Pokemon, level, LevelInt); ffi_arc_getter!(Pokemon, experience, u32); ffi_arc_getter!(Pokemon, unique_identifier, u32); ffi_arc_getter!(Pokemon, gender, Gender); ffi_arc_getter!(Pokemon, coloring, u8); #[no_mangle] extern "C" fn pokemon_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().held_item().read().as_ref() { v.clone().into() } else { IdentifiablePointer::none() } } #[no_mangle] extern "C" fn pokemon_has_held_item(ptr: ExternPointer>, name: *const c_char) -> u8 { let name = unsafe { CStr::from_ptr(name) }.into(); if ptr.as_ref().has_held_item(&name) { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_set_held_item( ptr: ExternPointer>, item: ExternPointer>, ) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().set_held_item(item.as_ref()) { v.clone().into() } else { IdentifiablePointer::none() } } #[no_mangle] extern "C" fn pokemon_remove_held_item(ptr: ExternPointer>) -> IdentifiablePointer> { if let Some(v) = ptr.as_ref().remove_held_item() { v.clone().into() } else { IdentifiablePointer::none() } } #[no_mangle] extern "C" fn pokemon_consume_held_item(ptr: ExternPointer>) -> u8 { if ptr.as_ref().consume_held_item() { 1 } else { 0 } } ffi_arc_getter!(Pokemon, current_health, u32); ffi_arc_getter!(Pokemon, max_health, u32); ffi_arc_getter!(Pokemon, weight, f32); ffi_arc_getter!(Pokemon, height, f32); #[no_mangle] extern "C" fn pokemon_nickname(ptr: ExternPointer>) -> *mut c_char { let name = ptr.as_ref().nickname(); if let Some(v) = name { CString::new(v.as_str()).unwrap().into_raw() } else { std::ptr::null_mut() } } #[no_mangle] extern "C" fn pokemon_real_ability_is_hidden(ptr: ExternPointer>) -> u8 { if ptr.as_ref().real_ability().hidden { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_real_ability_index(ptr: ExternPointer>) -> u8 { ptr.as_ref().real_ability().index } ffi_vec_value_getters!(Pokemon, types, TypeIdentifier); #[no_mangle] extern "C" fn pokemon_learned_move_get( ptr: ExternPointer>, index: usize, ) -> IdentifiablePointer> { if let Some(Some(v)) = ptr.as_ref().learned_moves().read().get(index) { v.clone().into() } else { IdentifiablePointer::none() } } #[no_mangle] extern "C" fn pokemon_flat_stats(ptr: ExternPointer>) -> IdentifiablePointer> { (ptr.as_ref().flat_stats() as *const StatisticSet).into() } #[no_mangle] extern "C" fn pokemon_boosted_stats(ptr: ExternPointer>) -> IdentifiablePointer> { (ptr.as_ref().boosted_stats() as *const StatisticSet).into() } #[no_mangle] extern "C" fn pokemon_get_stat_boost(ptr: ExternPointer>, statistic: Statistic) -> i8 { ptr.as_ref().stat_boost(statistic) } #[no_mangle] extern "C" fn pokemon_change_stat_boost( ptr: ExternPointer>, stat: Statistic, diff_amount: i8, self_inflicted: u8, ) -> u8 { if ptr.as_ref().change_stat_boost(stat, diff_amount, self_inflicted == 1) { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_get_individual_value(ptr: ExternPointer>, stat: Statistic) -> u8 { ptr.as_ref().individual_values().get_stat(stat) } #[no_mangle] extern "C" fn pokemon_set_individual_value(ptr: ExternPointer>, stat: Statistic, value: u8) { ptr.as_ref().individual_values().set_stat(stat, value); ptr.as_ref().recalculate_flat_stats(); } #[no_mangle] extern "C" fn pokemon_get_effort_value(ptr: ExternPointer>, stat: Statistic) -> u8 { ptr.as_ref().effort_values().get_stat(stat) } #[no_mangle] extern "C" fn pokemon_set_effort_value(ptr: ExternPointer>, stat: Statistic, value: u8) { ptr.as_ref().effort_values().set_stat(stat, value); ptr.as_ref().recalculate_flat_stats(); } #[no_mangle] extern "C" fn pokemon_get_battle(ptr: ExternPointer>) -> IdentifiablePointer { if let Some(v) = ptr.as_ref().get_battle() { (v as *const Battle).into() } else { IdentifiablePointer::none() } } #[no_mangle] extern "C" fn pokemon_get_battle_side_index(ptr: ExternPointer>) -> u8 { ptr.as_ref().get_battle_side_index().unwrap_or_default() } #[no_mangle] extern "C" fn pokemon_get_battle_index(ptr: ExternPointer>) -> u8 { ptr.as_ref().get_battle_index().unwrap_or_default() } #[no_mangle] extern "C" fn pokemon_is_ability_overriden(ptr: ExternPointer>) -> u8 { if ptr.as_ref().is_ability_overriden() { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_active_ability(ptr: ExternPointer>) -> IdentifiablePointer { (ptr.as_ref().active_ability() as *const Ability).into() } #[no_mangle] extern "C" fn pokemon_allowed_experience_gain(ptr: ExternPointer>) -> u8 { if ptr.as_ref().allowed_experience_gain() { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_nature(ptr: ExternPointer>) -> IdentifiablePointer> { ptr.as_ref().nature().clone().into() } #[no_mangle] extern "C" fn pokemon_recalculate_flat_stats(ptr: ExternPointer>) { ptr.as_ref().recalculate_flat_stats() } #[no_mangle] extern "C" fn pokemon_recalculate_boosted_stats(ptr: ExternPointer>) { ptr.as_ref().recalculate_boosted_stats() } #[no_mangle] extern "C" fn pokemon_change_species( ptr: ExternPointer>, species: ExternPointer>, form: ExternPointer>, ) { ptr.as_ref() .change_species(species.as_ref().clone(), form.as_ref().clone()) } #[no_mangle] extern "C" fn pokemon_change_form(ptr: ExternPointer>, form: ExternPointer>) { ptr.as_ref().change_form(form.as_ref()) } #[no_mangle] extern "C" fn pokemon_is_usable(ptr: ExternPointer>) -> u8 { if ptr.as_ref().is_usable() { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_is_fainted(ptr: ExternPointer>) -> u8 { if ptr.as_ref().is_fainted() { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_is_on_battlefield(ptr: ExternPointer>) -> u8 { if ptr.as_ref().is_on_battlefield() { 1 } else { 0 } } #[no_mangle] extern "C" fn pokemon_damage(ptr: ExternPointer>, damage: u32, source: DamageSource) { ptr.as_ref().damage(damage, source) } #[no_mangle] extern "C" fn pokemon_heal(ptr: ExternPointer>, amount: u32, allow_revive: u8) -> bool { ptr.as_ref().heal(amount, allow_revive == 1) } #[no_mangle] extern "C" fn pokemon_learn_move( ptr: ExternPointer>, move_name: *const c_char, learn_method: MoveLearnMethod, ) { unsafe { ptr.as_ref().learn_move(&CStr::from_ptr(move_name).into(), learn_method) } } #[no_mangle] extern "C" fn pokemon_clear_status(ptr: ExternPointer>) { ptr.as_ref().clear_status() }