diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs index fe47942..87bfecf 100644 --- a/src/ship/packet/handler/message.rs +++ b/src/ship/packet/handler/message.rs @@ -406,6 +406,7 @@ where // TODO: convenience function for giving exp and checking levelups (un-duplicate code here and `request_exp`) // TODO: use real errors (Idunnoman) // TODO: create InventoryError::CannotGetItemHandle or something +#[allow(clippy::too_many_arguments)] pub async fn player_steals_exp (id: ClientId, expsteal: &ExperienceSteal, entity_gateway: &mut EG, @@ -433,87 +434,87 @@ where let monster_stats = room.monster_stats.get(&monster.monster).ok_or(ShipError::UnknownMonster(monster.monster))?; let remaining_exp = monster_stats.exp - monster.stolen_exp[area_client.local_client.id() as usize]; - if remaining_exp <= 0 { - Ok(Box::new(None.into_iter())) - } else { - let char_special_modifier: f32 = if client.character.char_class.is_android() { - if room.mode.difficulty() == crate::ship::room::Difficulty::Ultimate { - 0.3 + if remaining_exp > 0 { + let char_special_modifier: f32 = if client.character.char_class.is_android() { + if room.mode.difficulty() == crate::ship::room::Difficulty::Ultimate { + 0.3 + } else { + 0.0 + } } else { 0.0 + }; + + let equipped_weapon_handle = item_manager + .get_character_inventory_mut(&client.character)? + .get_equipped_weapon_handle() + .ok_or(ItemManagerError::CannotGetIndividualItem)?; + + let equipped_weapon = &equipped_weapon_handle + .item() + .ok_or(ItemManagerError::Idunnoman)? + .individual() + .ok_or(ItemManagerError::Idunnoman)?.item; + + let special_exp_ratio: f32 = { + match equipped_weapon { + ItemDetail::Weapon(weapon) => match weapon.special { + Some(WeaponSpecial::Masters) => 0.08, + Some(WeaponSpecial::Lords) => 0.10, + Some(WeaponSpecial::Kings) => 0.12, + _ => 0.0, // TODO: error - stealing exp with wrong special + }, + ItemDetail::ESWeapon(esweapon) => match esweapon.special { + Some(ESWeaponSpecial::Kings) => 0.12, + _ => 0.0, // TODO: error - stealing exp with wrong special + }, + _ => 0.0, // TODO: error - stealing exp without a weapon!! + } + }; + + let weapon_special_reduction: f32 = { + match equipped_weapon { + ItemDetail::Weapon(weapon) => weapon.weapon.special_penalty(), + ItemDetail::ESWeapon(_esweapon) => 0.0, + _ => 1.0, // unreachable? + } + }; + + let exp_earned = std::cmp::min( + ((monster_stats.exp as f32 * (char_special_modifier + special_exp_ratio)).clamp(1.0, 80.0) * (1.0 - weapon_special_reduction)) as u32, + remaining_exp); + + monster.steal_exp(exp_earned, area_client.local_client.id() as usize); + println!("monster info: {:?}", monster); + + let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; + let gain_exp_pkt = builder::message::character_gained_exp(area_client, exp_earned); + let mut exp_pkts: Box + Send> = Box::new(clients_in_area.clone().into_iter() + .map(move |c| { + (c.client, SendShipPacket::Message(Message::new(GameMessage::GiveCharacterExp(gain_exp_pkt.clone())))) + })); + + let before_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); + let after_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp + exp_earned); + let level_up = before_level != after_level; + + if level_up { + let (_, before_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); + let (after_level, after_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp + exp_earned); + + let level_up_pkt = builder::message::character_leveled_up(area_client, after_level, before_stats, after_stats); + exp_pkts = Box::new(exp_pkts.chain(clients_in_area.into_iter() + .map(move |c| { + (c.client, SendShipPacket::Message(Message::new(GameMessage::PlayerLevelUp(level_up_pkt.clone())))) + }))) } + + client.character.exp += exp_earned; + entity_gateway.save_character(&client.character).await?; + + Ok(exp_pkts) } else { - 0.0 - }; - - let equipped_weapon_handle = item_manager - .get_character_inventory_mut(&client.character)? - .get_equipped_weapon_handle() - .ok_or(ItemManagerError::CannotGetIndividualItem)?; - - let equipped_weapon = &equipped_weapon_handle - .item() - .ok_or(ItemManagerError::Idunnoman)? - .individual() - .ok_or(ItemManagerError::Idunnoman)?.item; - - let special_exp_ratio: f32 = { - match equipped_weapon { - ItemDetail::Weapon(weapon) => match weapon.special { - Some(WeaponSpecial::Masters) => 0.08, - Some(WeaponSpecial::Lords) => 0.10, - Some(WeaponSpecial::Kings) => 0.12, - _ => 0.0, // TODO: error - stealing exp with wrong special - }, - ItemDetail::ESWeapon(esweapon) => match esweapon.special { - Some(ESWeaponSpecial::Kings) => 0.12, - _ => 0.0, // TODO: error - stealing exp with wrong special - }, - _ => 0.0, // TODO: error - stealing exp without a weapon!! - } - }; - - let weapon_special_reduction: f32 = { - match equipped_weapon { - ItemDetail::Weapon(weapon) => weapon.weapon.special_penalty(), - ItemDetail::ESWeapon(_esweapon) => 0.0, - _ => 1.0, // unreachable? - } - }; - - let exp_earned = std::cmp::min( - ((monster_stats.exp as f32 * (char_special_modifier + special_exp_ratio)).clamp(1.0, 80.0) * (1.0 - weapon_special_reduction)) as u32, - remaining_exp); - - monster.steal_exp(exp_earned, area_client.local_client.id() as usize); - println!("monster info: {:?}", monster); - - let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; - let gain_exp_pkt = builder::message::character_gained_exp(area_client, exp_earned); - let mut exp_pkts: Box + Send> = Box::new(clients_in_area.clone().into_iter() - .map(move |c| { - (c.client, SendShipPacket::Message(Message::new(GameMessage::GiveCharacterExp(gain_exp_pkt.clone())))) - })); - - let before_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp); - let after_level = level_table.get_level_from_exp(client.character.char_class, client.character.exp + exp_earned); - let level_up = before_level != after_level; - - if level_up { - let (_, before_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp); - let (after_level, after_stats) = level_table.get_stats_from_exp(client.character.char_class, client.character.exp + exp_earned); - - let level_up_pkt = builder::message::character_leveled_up(area_client, after_level, before_stats, after_stats); - exp_pkts = Box::new(exp_pkts.chain(clients_in_area.into_iter() - .map(move |c| { - (c.client, SendShipPacket::Message(Message::new(GameMessage::PlayerLevelUp(level_up_pkt.clone())))) - }))) - } - - client.character.exp += exp_earned; - entity_gateway.save_character(&client.character).await?; - - Ok(exp_pkts) + Ok(Box::new(None.into_iter())) } } } \ No newline at end of file