diff --git a/src/bin/main.rs b/src/bin/main.rs
index 152b79f..f43276e 100644
--- a/src/bin/main.rs
+++ b/src/bin/main.rs
@@ -137,9 +137,9 @@ fn main() {
                 NewItemEntity {
                     item: ItemDetail::Weapon(
                         item::weapon::Weapon {
-                            weapon: item::weapon::WeaponType::Vjaya,
+                            weapon: item::weapon::WeaponType::Ripper,
                             grind: 5,
-                            special: Some(item::weapon::WeaponSpecial::Charge),
+                            special: Some(item::weapon::WeaponSpecial::Kings),
                             attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 40}),
                                     Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
                                     None,],
@@ -153,7 +153,7 @@ fn main() {
                         item::weapon::Weapon {
                             weapon: item::weapon::WeaponType::Vulcan,
                             grind: 5,
-                            special: Some(item::weapon::WeaponSpecial::Charge),
+                            special: Some(item::weapon::WeaponSpecial::Kings),
                             attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
                                     Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
                                     None,],
diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs
index 11a8709..8ab6c0d 100644
--- a/src/entity/item/weapon.rs
+++ b/src/entity/item/weapon.rs
@@ -1421,6 +1421,80 @@ impl WeaponType {
            _ => Err(ItemParseError::InvalidWeaponType),
         }
     }
+
+    pub fn special_penalty(&self) -> f32 {
+        match(self) {
+            WeaponType::Saber => 0.0,
+            WeaponType::Brand => 0.0,
+            WeaponType::Buster => 0.0,
+            WeaponType::Pallasch => 0.0,
+            WeaponType::Gladius => 0.0,
+            WeaponType::Handgun => 0.0,
+            WeaponType::Autogun => 0.0,
+            WeaponType::Lockgun => 0.0,
+            WeaponType::Railgun => 0.0,
+            WeaponType::Raygun => 0.0,
+            WeaponType::Rifle => 0.0,
+            WeaponType::Sniper => 0.0,
+            WeaponType::Blaster => 0.0,
+            WeaponType::Beam => 0.0,
+            WeaponType::Laser => 0.0,
+            WeaponType::Cane => 0.0,
+            WeaponType::Stick => 0.0,
+            WeaponType::Mace => 0.0,
+            WeaponType::Club => 0.0,
+            WeaponType::Rod => 0.0,
+            WeaponType::Pole => 0.0,
+            WeaponType::Pillar => 0.0,
+            WeaponType::Striker => 0.0,
+            WeaponType::Wand => 0.0,
+            WeaponType::Staff => 0.0,
+            WeaponType::Baton => 0.0,
+            WeaponType::Scepter => 0.0,
+
+            WeaponType::Sword => 0.5,
+            WeaponType::Gigush => 0.5,
+            WeaponType::Breaker => 0.5,
+            WeaponType::Claymore => 0.5,
+            WeaponType::Calibur => 0.5,
+            WeaponType::FlowensSword => 0.5,
+            WeaponType::LastSurvivor => 0.5,
+            WeaponType::DragonSlayer => 0.5,
+            WeaponType::Dagger => 0.5,
+            WeaponType::Knife => 0.5,
+            WeaponType::Blade => 0.5,
+            WeaponType::Edge => 0.5,
+            WeaponType::Ripper => 0.5,
+            WeaponType::BladeDance => 0.5,
+            WeaponType::BloodyArt => 0.5,
+            WeaponType::CrossScar => 0.5,
+            WeaponType::ZeroDivide => 0.5,
+            WeaponType::TwoKamui => 0.5,
+            WeaponType::Partisan => 0.5,
+            WeaponType::Halbert => 0.5,
+            WeaponType::Glaive => 0.5,
+            WeaponType::Berdys => 0.5,
+            WeaponType::Gungnir => 0.5,
+
+            WeaponType::Slicer => 0.6666,
+            WeaponType::Spinner => 0.6666,
+            WeaponType::Cutter => 0.6666,
+            WeaponType::Sawcer => 0.6666,
+            WeaponType::Diska => 0.6666,
+            WeaponType::Mechgun => 0.6666,
+            WeaponType::Assault => 0.6666,
+            WeaponType::Repeater => 0.6666,
+            WeaponType::Gatling => 0.6666,
+            WeaponType::Vulcan => 0.6666,
+            WeaponType::Shot => 0.6666,
+            WeaponType::Spread => 0.6666,
+            WeaponType::Cannon => 0.6666,
+            WeaponType::Launcher => 0.6666,
+            WeaponType::Arms => 0.6666,
+
+            _ => 1.0,
+        }
+    }
 }
 
 
diff --git a/src/ship/monster.rs b/src/ship/monster.rs
index 1bdb5b7..8dab9f1 100644
--- a/src/ship/monster.rs
+++ b/src/ship/monster.rs
@@ -148,6 +148,44 @@ pub enum MonsterType {
     Kondrieu,
 }
 
+impl MonsterType {
+    pub fn is_boss(&self) -> bool {
+        matches!(self,
+            MonsterType::Dragon |
+            MonsterType::DeRolLe |
+            MonsterType::DeRolLeBody |
+            MonsterType::DeRolLeMine |
+            MonsterType::VolOptPartA |
+            MonsterType::VolOptPillar |
+            MonsterType::VolOptMonitor |
+            MonsterType::VolOptAmp |
+            MonsterType::VolOptCore |
+            MonsterType::VolOptUnused |
+            MonsterType::VolOpt |
+            MonsterType::VolOptTrap |
+            MonsterType::DarkFalz |
+            MonsterType::DarkFalz1 |
+            MonsterType::DarkFalz2 |
+            MonsterType::DarkFalz3 |
+            MonsterType::Darvant |
+            MonsterType::UltDarvant |
+            MonsterType::Epsiguard | // TODO: is epsilon core a boss?
+            MonsterType::BarbaRay |
+            MonsterType::PigRay |
+            MonsterType::GolDragon |
+            MonsterType::GalGryphon |
+            MonsterType::OlgaFlow |
+            MonsterType::OlgaFlow1 |
+            MonsterType::OlgaFlow2 |
+            MonsterType::Gael |
+            MonsterType::Giel |
+            MonsterType::SaintMillion |
+            MonsterType::Shambertin |
+            MonsterType::Kondrieu
+        )
+    }
+}
+
 
 #[derive(serde::Deserialize, Debug)]
 pub struct MonsterStats {
diff --git a/src/ship/packet/handler/message.rs b/src/ship/packet/handler/message.rs
index 6f2997e..79c8c11 100644
--- a/src/ship/packet/handler/message.rs
+++ b/src/ship/packet/handler/message.rs
@@ -442,19 +442,18 @@ where
         0.0
     };
 
-     
-    let weapon_exp_ratio: f32 = {
-        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 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,
@@ -470,7 +469,15 @@ where
         }
     };
 
-    let exp_gain = (monster_stats.exp as f32 * (char_special_modifier + weapon_exp_ratio)).clamp(1.0, 80.0) as u32;
+    let weapon_special_reduction: f32 = {
+        match equipped_weapon {
+            ItemDetail::Weapon(weapon) => weapon.weapon.special_penalty(),
+            ItemDetail::ESWeapon(_esweapon) => 0.0,
+            _ => 0.0,
+        }
+    };
+
+    let exp_gain = ((monster_stats.exp as f32 * (char_special_modifier + special_exp_ratio)).clamp(1.0, 80.0) * (1.0 - weapon_special_reduction)) as u32;
 
     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_gain);
diff --git a/tests/test_exp_gain.rs b/tests/test_exp_gain.rs
index 4c2e5a3..3520f74 100644
--- a/tests/test_exp_gain.rs
+++ b/tests/test_exp_gain.rs
@@ -561,18 +561,118 @@ async fn test_exp_steal_no_android_boost_in_vhard() {
     assert!(c2.character.exp == 80000010);
 }
 
+#[async_std::test]
+async fn test_exp_steal_multihit_penalty() {
+    let mut entity_gateway = InMemoryGateway::default();
+
+    let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
+    char1.exp = 80000000;
+    char1.char_class = CharacterClass::HUcast;
+    entity_gateway.save_character(&char1).await.unwrap();
+
+    let mut p1_inv = Vec::new();
+    p1_inv.push(entity_gateway.create_item(
+        item::NewItemEntity {
+            item: item::ItemDetail::Weapon(
+                item::weapon::Weapon {
+                    weapon: item::weapon::WeaponType::Dagger,
+                    grind: 5,
+                    special: Some(item::weapon::WeaponSpecial::Kings),
+                    attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
+                            Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
+                            None,],
+                    tekked: true,
+                }
+            ),
+        }).await.unwrap());
+    
+    p1_inv.push(entity_gateway.create_item(
+        item::NewItemEntity {
+            item: item::ItemDetail::Weapon(
+                item::weapon::Weapon {
+                    weapon: item::weapon::WeaponType::Mechgun,
+                    grind: 5,
+                    special: Some(item::weapon::WeaponSpecial::Kings),
+                    attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
+                            Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
+                            None,],
+                    tekked: true,
+                }
+            ),
+        }).await.unwrap());
+    
+    let equipped = item::EquippedEntity {
+        weapon: Some(p1_inv[0].id),
+        armor: None,
+        shield: None,
+        unit: [None; 4],
+        mag: None,
+    };
+    entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
+    entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
+
+    let mut ship = Box::new(ShipServerState::builder()
+        .gateway(entity_gateway.clone())
+        .build());
+
+    log_in_char(&mut ship, ClientId(1), "a1", "a").await;
+    join_lobby(&mut ship, ClientId(1)).await;
+    create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
+
+    let enemy_id = {
+        let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
+        let enemy_id = (0..).filter_map(|i| {
+            room.maps.enemy_by_id(i).ok().and_then(|enemy| {
+                if enemy.monster == MonsterType::Booma {
+                    Some(i)
+                }
+                else {
+                    None
+                }
+            })
+        }).next().unwrap();
+        enemy_id
+    };
+
+    ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
+        client: 0,
+        target: 0,
+        client2: enemy_id as u8,
+        target2: 16,
+        enemy_id: enemy_id as u16,
+    })))).await.unwrap().for_each(drop);
+
+    let c1 = ship.clients.get(&ClientId(1)).unwrap();
+    assert!(c1.character.exp == 80000040);
+
+    // change equipped item
+    ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerEquipItem(PlayerEquipItem {
+        client: 0,
+        target: 0,
+        item_id: 0x10001,
+        sub_menu: 9,
+        unknown1: 0,
+    })))).await.unwrap().for_each(drop);
+
+    ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
+        client: 0,
+        target: 0,
+        client2: enemy_id as u8,
+        target2: 16,
+        enemy_id: enemy_id as u16,
+    })))).await.unwrap().for_each(drop);
+
+    let c1 = ship.clients.get(&ClientId(1)).unwrap();
+    assert!(c1.character.exp == 80000066);
+}
+
 #[async_std::test]
 async fn test_exp_steal_doesnt_exceed_100p() {
     assert!(false)
 }
 
 #[async_std::test]
-async fn test_exp_steal_multihit_penalty() {
-    assert!(false)
-}
-
-#[async_std::test]
-async fn test_each_client_can_steal_exp_from_same_enemy() {
+async fn test_each_client_can_steal_full_exp_from_same_enemy() {
     assert!(false)
 }