Fixes for assurance, implementation of avalanche
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2023-06-30 18:03:57 +02:00
parent ddaa2dab31
commit 3472d39bed
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
12 changed files with 223 additions and 73 deletions

View File

@ -12,6 +12,7 @@ crate-type = ["cdylib"]
pkmn_lib_interface = { path = "../pkmn_lib_interface" }
paste = { version = "1.0.7" }
atomic_float = "0.1.0"
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
[dev-dependencies]
pkmn_lib_interface = { path = "../pkmn_lib_interface", features = ["mock_data"] }

View File

@ -1,3 +1,4 @@
pub use crate::alloc::string::ToString;
pub use crate::script;
pub use alloc::boxed::Box;
pub use alloc::rc::Rc;

View File

@ -1,10 +1,13 @@
use crate::common_usings::*;
use crate::pokemon::assurance_data::AssuranceData;
use crate::side::double_power_if_target_damaged_in_turn_data::DoublePowerIfTargetDamagedInTurnData;
use pkmn_lib_interface::PkmnResult;
script!(Assurance, "assurance");
script!(
DoublePowerIfTargetDamagedInTurn,
"double_power_if_target_damaged_in_turn"
);
impl Script for Assurance {
impl Script for DoublePowerIfTargetDamagedInTurn {
fn new() -> Self {
Self {}
}
@ -30,7 +33,7 @@ impl Script for Assurance {
.get(data.target_side() as usize)
.unwrap()
.clone();
side.add_volatile(AssuranceData::create_for_assurance(data.target_index()))?;
side.add_volatile(DoublePowerIfTargetDamagedInTurnData::create_for_assurance())?;
}
Ok(())
}
@ -42,11 +45,11 @@ impl Script for Assurance {
_hit: u8,
base_power: &mut Saturating<u8>,
) -> PkmnResult<()> {
if let Some(s) = get_volatile_as::<AssuranceData>(
if let Some(s) = get_volatile_as::<DoublePowerIfTargetDamagedInTurnData>(
target.battle_side()?.as_ref(),
AssuranceData::get_const_name(),
DoublePowerIfTargetDamagedInTurnData::get_const_name(),
)? {
if s.has_hit() {
if s.has_hit_for_pokemon(&target) {
*base_power *= 2;
}
}

View File

@ -0,0 +1,53 @@
use crate::common_usings::*;
use crate::pokemon::double_power_user_damaged_by_target_in_turn::DoublePowerUserDamagedByTargetInTurnData;
use pkmn_lib_interface::PkmnResult;
script!(
DoublePowerUserDamagedByTargetInTurn,
"double_power_user_damaged_by_target_in_turn"
);
impl Script for DoublePowerUserDamagedByTargetInTurn {
fn new() -> Self {
Self {}
}
fn get_name(&self) -> &'static str {
Self::get_const_name()
}
fn get_capabilities(&self) -> &[ScriptCapabilities] {
&[
ScriptCapabilities::OnBeforeTurn,
ScriptCapabilities::ChangeBasePower,
]
}
fn on_before_turn(&self, choice: TurnChoice) -> PkmnResult<()> {
let user = choice.user();
user.add_volatile(DoublePowerUserDamagedByTargetInTurnData::create())?;
Ok(())
}
fn change_base_power(
&self,
_move: ExecutingMove,
target: Pokemon,
_hit: u8,
base_power: &mut Saturating<u8>,
) -> PkmnResult<()> {
if let Some(s) = get_volatile_as::<DoublePowerUserDamagedByTargetInTurnData>(
target.battle_side()?.as_ref(),
DoublePowerUserDamagedByTargetInTurnData::get_const_name(),
)? {
if s.has_been_hit_by_pokemon(&target) {
*base_power *= 2;
}
}
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}

View File

@ -2,13 +2,14 @@ pub mod acrobatics;
pub mod acupressure;
pub mod after_you;
pub mod assist;
pub mod assurance;
pub mod attract;
pub mod aurora_veil;
pub mod automize;
pub mod change_all_target_stats;
pub mod change_target_stats;
pub mod cure_party_status;
pub mod double_power_if_target_damaged_in_turn;
pub mod double_power_user_damaged_by_target_in_turn;
pub mod drain;
pub mod flinch;
pub mod heal_each_end_of_turn;

View File

@ -1,61 +0,0 @@
use crate::common_usings::*;
script!(
AssuranceData,
"assurance_data",
for_position: u8,
has_hit: AtomicBool
);
impl Script for AssuranceData {
fn new() -> Self {
Self {
for_position: 0,
has_hit: AtomicBool::new(false),
}
}
fn get_name(&self) -> &'static str {
Self::get_const_name()
}
fn get_capabilities(&self) -> &[ScriptCapabilities] {
&[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage]
}
fn on_end_turn(&self) -> PkmnResult<()> {
let side = self.get_owner().unwrap().as_side();
side.remove_volatile(self)?;
Ok(())
}
fn on_damage(
&self,
pokemon: Pokemon,
_source: DamageSource,
_old_health: u32,
_new_health: u32,
) -> PkmnResult<()> {
if pokemon.battle_index()? == self.for_position {
self.has_hit.store(true, Ordering::Relaxed);
}
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl AssuranceData {
pub fn create_for_assurance(for_position: u8) -> Box<dyn Script> {
Box::new(Self {
for_position,
has_hit: AtomicBool::new(false),
})
}
pub fn has_hit(&self) -> bool {
self.has_hit.load(Ordering::Relaxed)
}
}

View File

@ -0,0 +1,81 @@
use crate::common_usings::*;
use pkmn_lib_interface::{pkmn_err, PkmnErr};
use spin::RwLock;
script!(
DoublePowerUserDamagedByTargetInTurnData,
"double_power_user_damaged_by_target_in_turn_data",
hits: RwLock<Vec<Pokemon>>
);
impl Script for DoublePowerUserDamagedByTargetInTurnData {
fn new() -> Self {
Self {
hits: Default::default(),
}
}
fn get_name(&self) -> &'static str {
Self::get_const_name()
}
fn get_capabilities(&self) -> &[ScriptCapabilities] {
&[
ScriptCapabilities::OnEndTurn,
ScriptCapabilities::OnIncomingHit,
]
}
fn on_incoming_hit(
&self,
executing_move: ExecutingMove,
target: Pokemon,
hit: u8,
) -> PkmnResult<()> {
// Only register hits that dealt damage
if executing_move
.get_hit_data(&target, hit)
.or(Err(pkmn_err!("Couldnt resolve hit")))?
.damage()?
== 0
{
return Ok(());
}
let user = executing_move.user();
let mut write_lock = self.hits.write();
// Check if the pokemon has already hit the pokemon. Bail out if it has.
for hit_pokemon in write_lock.iter() {
if hit_pokemon.reference() == user.reference() {
return Ok(());
}
}
write_lock.push(user);
Ok(())
}
fn on_end_turn(&self) -> PkmnResult<()> {
let pokemon = self.get_owner().unwrap().as_pokemon();
pokemon.remove_volatile(self)?;
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl DoublePowerUserDamagedByTargetInTurnData {
pub fn create() -> Box<dyn Script> {
Box::new(Self::new())
}
pub fn has_been_hit_by_pokemon(&self, pokemon: &Pokemon) -> bool {
let read_lock = self.hits.read();
for hit_pokemon in read_lock.iter() {
if hit_pokemon.reference() == pokemon.reference() {
return true;
}
}
false
}
}

View File

@ -1,4 +1,4 @@
pub mod assurance_data;
pub mod double_power_user_damaged_by_target_in_turn;
pub mod flinch_effect;
pub mod heal_each_end_of_turn;
pub mod infatuated;

View File

@ -33,10 +33,11 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
crate::moves::assist::Assist,
crate::moves::acupressure::Acupressure,
crate::moves::struggle::Struggle,
crate::moves::assurance::Assurance,
crate::moves::cure_party_status::CurePartyStatus,
crate::moves::multi_hit_move::MultiHitMove,
crate::moves::double_power_if_target_damaged_in_turn::DoublePowerIfTargetDamagedInTurn,
crate::moves::heal_each_end_of_turn::HealEachEndOfTurn,
crate::moves::double_power_user_damaged_by_target_in_turn::DoublePowerUserDamagedByTargetInTurn,
crate::moves::aurora_veil::AuroraVeil,
crate::moves::change_all_target_stats::ChangeAllTargetStats,
crate::moves::after_you::AfterYou,
@ -60,9 +61,9 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
resolve_match! {
name.hash().unwrap(),
crate::pokemon::prevent_foes_exit::PreventFoesExitEffect,
crate::pokemon::assurance_data::AssuranceData,
crate::pokemon::flinch_effect::FlinchEffect,
crate::pokemon::heal_each_end_of_turn::HealEachEndOfTurnEffect,
crate::pokemon::double_power_user_damaged_by_target_in_turn::DoublePowerUserDamagedByTargetInTurnData,
crate::pokemon::infatuated::Infatuated,
}
},
@ -81,6 +82,7 @@ pub fn get_script(category: ScriptCategory, name: &StringKey) -> Option<Box<dyn
resolve_match! {
name.hash().unwrap(),
crate::side::light_screen::LightScreenEffect,
crate::side::double_power_if_target_damaged_in_turn_data::DoublePowerIfTargetDamagedInTurnData,
crate::side::aurora_veil_effect::AuroraVeilEffect,
}
},

View File

@ -0,0 +1,68 @@
use crate::common_usings::*;
use spin::RwLock;
script!(
DoublePowerIfTargetDamagedInTurnData,
"double_power_if_target_damaged_in_turn_data",
hits: RwLock<Vec<Pokemon>>
);
impl Script for DoublePowerIfTargetDamagedInTurnData {
fn new() -> Self {
Self {
hits: Default::default(),
}
}
fn get_name(&self) -> &'static str {
Self::get_const_name()
}
fn get_capabilities(&self) -> &[ScriptCapabilities] {
&[ScriptCapabilities::OnEndTurn, ScriptCapabilities::OnDamage]
}
fn on_end_turn(&self) -> PkmnResult<()> {
let side = self.get_owner().unwrap().as_side();
side.remove_volatile(self)?;
Ok(())
}
fn on_damage(
&self,
pokemon: Pokemon,
_source: DamageSource,
_old_health: u32,
_new_health: u32,
) -> PkmnResult<()> {
let mut write_lock = self.hits.write();
for hit_pokemon in write_lock.iter() {
if hit_pokemon.reference() == pokemon.reference() {
return Ok(());
}
}
write_lock.push(pokemon);
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl DoublePowerIfTargetDamagedInTurnData {
pub fn create_for_assurance() -> Box<dyn Script> {
Box::new(Self {
hits: Default::default(),
})
}
pub fn has_hit_for_pokemon(&self, pokemon: &Pokemon) -> bool {
for hit_pokemon in self.hits.read().iter() {
if hit_pokemon.reference() == pokemon.reference() {
return true;
}
}
false
}
}

View File

@ -1,2 +1,3 @@
pub mod aurora_veil_effect;
pub mod double_power_if_target_damaged_in_turn_data;
pub mod light_screen;

View File

@ -12,7 +12,7 @@ cstr_core = { version = "0.2.6", features = ["nightly"] }
enumflags2 = { version = "0.7.5", default-features = false }
spin = { version = "0.9.4", default-features = false, features = ["rwlock"] }
paste = { version = "1.0.7" }
hashbrown = { version = "0.13.2" }
hashbrown = { version = "0.14.0" }
dlmalloc = { version = "0.2.4", features = ["global"] }
mockall = { version = "0.11.2", optional = true, features = ["nightly"] }
num-traits = { version = "0.2", default-features = false }