You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

583 lines
21 KiB

5 years ago
3 years ago
5 years ago
3 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
3 years ago
  1. use elseware::common::serverstate::{ClientId, ServerState};
  2. use elseware::entity::character::{CharacterClass};
  3. use elseware::entity::gateway::{EntityGateway, InMemoryGateway};
  4. use elseware::common::leveltable::CharacterLevelTable;
  5. use elseware::ship::ship::{ShipServerState, SendShipPacket, RecvShipPacket};
  6. use elseware::ship::monster::MonsterType;
  7. use elseware::entity::item;
  8. use elseware::ship::room::{Difficulty};
  9. use libpso::packet::ship::*;
  10. use libpso::packet::messages::*;
  11. #[path = "common.rs"]
  12. mod common;
  13. use common::*;
  14. #[async_std::test]
  15. async fn test_character_gains_exp() {
  16. let mut entity_gateway = InMemoryGateway::default();
  17. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  18. let mut ship = Box::new(ShipServerState::builder()
  19. .gateway(entity_gateway.clone())
  20. .build());
  21. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  22. join_lobby(&mut ship, ClientId(1)).await;
  23. create_room(&mut ship, ClientId(1), "room", "").await;
  24. let (enemy_id, exp) = {
  25. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  26. let (enemy_id, map_enemy) = (0..).filter_map(|i| {
  27. room.maps.enemy_by_id(i).map(|enemy| {
  28. (i, enemy)
  29. }).ok()
  30. }).next().unwrap();
  31. let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap();
  32. (enemy_id, map_enemy_stats.exp)
  33. };
  34. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{
  35. client: enemy_id as u8,
  36. target: 16,
  37. enemy_id: enemy_id as u16,
  38. client_id: 0,
  39. unused: 0,
  40. last_hitter: 1,
  41. })))).await.unwrap().for_each(drop);
  42. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  43. assert!(exp == c1.character.exp);
  44. }
  45. #[async_std::test]
  46. async fn test_character_levels_up() {
  47. let mut entity_gateway = InMemoryGateway::default();
  48. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  49. char1.exp = 49;
  50. entity_gateway.save_character(&char1).await.unwrap();
  51. let mut ship = Box::new(ShipServerState::builder()
  52. .gateway(entity_gateway.clone())
  53. .build());
  54. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  55. join_lobby(&mut ship, ClientId(1)).await;
  56. create_room(&mut ship, ClientId(1), "room", "").await;
  57. let enemy_id = {
  58. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  59. (0..).filter_map(|i| {
  60. room.maps.enemy_by_id(i).map(|_| {
  61. i
  62. }).ok()
  63. }).next().unwrap()
  64. };
  65. let levelup_pkt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{
  66. client: enemy_id as u8,
  67. target: 16,
  68. enemy_id: enemy_id as u16,
  69. client_id: 0,
  70. unused: 0,
  71. last_hitter: 1,
  72. })))).await.unwrap().collect::<Vec<_>>();
  73. assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 2, ..})})));
  74. let leveltable = CharacterLevelTable::default();
  75. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  76. assert!(leveltable.get_level_from_exp(c1.character.char_class, c1.character.exp) == 2);
  77. }
  78. #[async_std::test]
  79. async fn test_character_levels_up_multiple_times() {
  80. let mut entity_gateway = InMemoryGateway::default();
  81. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  82. let mut ship = Box::new(ShipServerState::builder()
  83. .gateway(entity_gateway.clone())
  84. .build());
  85. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  86. join_lobby(&mut ship, ClientId(1)).await;
  87. create_room(&mut ship, ClientId(1), "room", "").await;
  88. let (enemy_id, exp) = {
  89. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  90. let (enemy_id, map_enemy) = (0..).filter_map(|i| {
  91. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  92. if enemy.monster == MonsterType::DarkFalz2 {
  93. Some((i, enemy))
  94. }
  95. else {
  96. None
  97. }
  98. })
  99. }).next().unwrap();
  100. let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap();
  101. (enemy_id, map_enemy_stats.exp)
  102. };
  103. let levelup_pkt = ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{
  104. client: enemy_id as u8,
  105. target: 16,
  106. enemy_id: enemy_id as u16,
  107. client_id: 0,
  108. unused: 0,
  109. last_hitter: 1,
  110. })))).await.unwrap().collect::<Vec<_>>();
  111. assert!(matches!(levelup_pkt[1].1, SendShipPacket::Message(Message {msg: GameMessage::PlayerLevelUp(PlayerLevelUp {lvl: 8, ..})})));
  112. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  113. assert!(exp == c1.character.exp);
  114. }
  115. #[async_std::test]
  116. async fn test_one_character_gets_full_exp_and_other_attacker_gets_partial() {
  117. let mut entity_gateway = InMemoryGateway::default();
  118. let (_user1, _char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  119. let (_user2, _char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  120. let mut ship = Box::new(ShipServerState::builder()
  121. .gateway(entity_gateway.clone())
  122. .build());
  123. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  124. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  125. join_lobby(&mut ship, ClientId(1)).await;
  126. join_lobby(&mut ship, ClientId(2)).await;
  127. create_room(&mut ship, ClientId(1), "room", "").await;
  128. join_room(&mut ship, ClientId(2), 0).await;
  129. let (enemy_id, exp) = {
  130. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  131. let (enemy_id, map_enemy) = (0..).filter_map(|i| {
  132. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  133. if enemy.monster == MonsterType::DarkFalz2 {
  134. Some((i, enemy))
  135. }
  136. else {
  137. None
  138. }
  139. })
  140. }).next().unwrap();
  141. let map_enemy_stats = room.monster_stats.get(&map_enemy.monster).unwrap();
  142. (enemy_id, map_enemy_stats.exp)
  143. };
  144. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{
  145. client: enemy_id as u8,
  146. target: 16,
  147. enemy_id: enemy_id as u16,
  148. client_id: 0,
  149. unused: 0,
  150. last_hitter: 1,
  151. })))).await.unwrap().for_each(drop);
  152. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::RequestExp(RequestExp{
  153. client: enemy_id as u8,
  154. target: 16,
  155. enemy_id: enemy_id as u16,
  156. client_id: 0,
  157. unused: 0,
  158. last_hitter: 0,
  159. })))).await.unwrap().for_each(drop);
  160. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  161. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  162. assert!(c1.character.exp == exp);
  163. assert!(c2.character.exp == (exp as f32 * 0.8) as u32);
  164. }
  165. #[async_std::test]
  166. async fn test_exp_steal_min_1() {
  167. let mut entity_gateway = InMemoryGateway::default();
  168. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  169. let mut p1_inv = Vec::new();
  170. p1_inv.push(entity_gateway.create_item(
  171. item::NewItemEntity {
  172. item: item::ItemDetail::Weapon(
  173. item::weapon::Weapon {
  174. weapon: item::weapon::WeaponType::Raygun,
  175. grind: 5,
  176. special: Some(item::weapon::WeaponSpecial::Kings),
  177. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  178. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  179. None,],
  180. tekked: true,
  181. }
  182. ),
  183. }).await.unwrap());
  184. let equipped = item::EquippedEntity {
  185. weapon: Some(p1_inv[0].id),
  186. armor: None,
  187. shield: None,
  188. unit: [None; 4],
  189. mag: None,
  190. };
  191. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  192. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  193. let mut ship = Box::new(ShipServerState::builder()
  194. .gateway(entity_gateway.clone())
  195. .build());
  196. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  197. join_lobby(&mut ship, ClientId(1)).await;
  198. create_room(&mut ship, ClientId(1), "room", "").await;
  199. let enemy_id = {
  200. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  201. let enemy_id = (0..).filter_map(|i| {
  202. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  203. if enemy.monster == MonsterType::Booma {
  204. Some(i)
  205. }
  206. else {
  207. None
  208. }
  209. })
  210. }).next().unwrap();
  211. enemy_id
  212. };
  213. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  214. client: 0,
  215. target: 0,
  216. client2: enemy_id as u8,
  217. target2: 16,
  218. enemy_id: enemy_id as u16,
  219. })))).await.unwrap().for_each(drop);
  220. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  221. assert!(c1.character.exp == 1);
  222. }
  223. #[async_std::test]
  224. async fn test_exp_steal_max_80() {
  225. let mut entity_gateway = InMemoryGateway::default();
  226. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  227. char1.exp = 80000000;
  228. char1.char_class = CharacterClass::HUcast;
  229. entity_gateway.save_character(&char1).await.unwrap();
  230. let mut p1_inv = Vec::new();
  231. p1_inv.push(entity_gateway.create_item(
  232. item::NewItemEntity {
  233. item: item::ItemDetail::Weapon(
  234. item::weapon::Weapon {
  235. weapon: item::weapon::WeaponType::Raygun,
  236. grind: 5,
  237. special: Some(item::weapon::WeaponSpecial::Kings),
  238. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  239. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  240. None,],
  241. tekked: true,
  242. }
  243. ),
  244. }).await.unwrap());
  245. let equipped = item::EquippedEntity {
  246. weapon: Some(p1_inv[0].id),
  247. armor: None,
  248. shield: None,
  249. unit: [None; 4],
  250. mag: None,
  251. };
  252. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  253. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  254. let mut ship = Box::new(ShipServerState::builder()
  255. .gateway(entity_gateway.clone())
  256. .build());
  257. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  258. join_lobby(&mut ship, ClientId(1)).await;
  259. create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
  260. let enemy_id = {
  261. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  262. let enemy_id = (0..).filter_map(|i| {
  263. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  264. if enemy.monster == MonsterType::Booma {
  265. Some(i)
  266. }
  267. else {
  268. None
  269. }
  270. })
  271. }).next().unwrap();
  272. enemy_id
  273. };
  274. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  275. client: 0,
  276. target: 0,
  277. client2: enemy_id as u8,
  278. target2: 16,
  279. enemy_id: enemy_id as u16,
  280. })))).await.unwrap().for_each(drop);
  281. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  282. assert!(c1.character.exp == 80000080);
  283. }
  284. #[async_std::test]
  285. async fn test_exp_steal_android_boost_in_ultimate() {
  286. let mut entity_gateway = InMemoryGateway::default();
  287. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  288. char1.exp = 80000000;
  289. char1.char_class = CharacterClass::HUcast;
  290. entity_gateway.save_character(&char1).await.unwrap();
  291. let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  292. char2.exp = 80000000;
  293. char2.char_class = CharacterClass::HUmar;
  294. entity_gateway.save_character(&char2).await.unwrap();
  295. let mut p1_inv = Vec::new();
  296. p1_inv.push(entity_gateway.create_item(
  297. item::NewItemEntity {
  298. item: item::ItemDetail::Weapon(
  299. item::weapon::Weapon {
  300. weapon: item::weapon::WeaponType::Raygun,
  301. grind: 5,
  302. special: Some(item::weapon::WeaponSpecial::Kings),
  303. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  304. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  305. None,],
  306. tekked: true,
  307. }
  308. ),
  309. }).await.unwrap());
  310. let equipped = item::EquippedEntity {
  311. weapon: Some(p1_inv[0].id),
  312. armor: None,
  313. shield: None,
  314. unit: [None; 4],
  315. mag: None,
  316. };
  317. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  318. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  319. let mut p2_inv = Vec::new();
  320. p2_inv.push(entity_gateway.create_item(
  321. item::NewItemEntity {
  322. item: item::ItemDetail::Weapon(
  323. item::weapon::Weapon {
  324. weapon: item::weapon::WeaponType::Raygun,
  325. grind: 5,
  326. special: Some(item::weapon::WeaponSpecial::Kings),
  327. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  328. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  329. None,],
  330. tekked: true,
  331. }
  332. ),
  333. }).await.unwrap());
  334. let equipped = item::EquippedEntity {
  335. weapon: Some(p2_inv[0].id),
  336. armor: None,
  337. shield: None,
  338. unit: [None; 4],
  339. mag: None,
  340. };
  341. entity_gateway.set_character_equips(&char2.id, &equipped).await.unwrap();
  342. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  343. let mut ship = Box::new(ShipServerState::builder()
  344. .gateway(entity_gateway.clone())
  345. .build());
  346. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  347. join_lobby(&mut ship, ClientId(1)).await;
  348. create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
  349. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  350. join_lobby(&mut ship, ClientId(2)).await;
  351. join_room(&mut ship, ClientId(2), 0).await;
  352. let enemy_id = {
  353. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  354. let enemy_id = (0..).filter_map(|i| {
  355. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  356. if enemy.monster == MonsterType::Booma {
  357. Some(i)
  358. }
  359. else {
  360. None
  361. }
  362. })
  363. }).next().unwrap();
  364. enemy_id
  365. };
  366. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  367. client: 0,
  368. target: 0,
  369. client2: enemy_id as u8,
  370. target2: 16,
  371. enemy_id: enemy_id as u16,
  372. })))).await.unwrap().for_each(drop);
  373. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  374. client: 0,
  375. target: 0,
  376. client2: enemy_id as u8,
  377. target2: 16,
  378. enemy_id: enemy_id as u16,
  379. })))).await.unwrap().for_each(drop);
  380. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  381. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  382. println!("c1 exp: {:?}, c2 exp: {:?}", c1.character.exp, c2.character.exp);
  383. assert!(c1.character.exp == 80000080);
  384. assert!(c2.character.exp == 80000032);
  385. }
  386. #[async_std::test]
  387. async fn test_exp_steal_no_android_boost_in_vhard() {
  388. let mut entity_gateway = InMemoryGateway::default();
  389. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  390. char1.exp = 80000000;
  391. char1.char_class = CharacterClass::HUcast;
  392. entity_gateway.save_character(&char1).await.unwrap();
  393. let (_user2, mut char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  394. char2.exp = 80000000;
  395. char2.char_class = CharacterClass::HUmar;
  396. entity_gateway.save_character(&char2).await.unwrap();
  397. let mut p1_inv = Vec::new();
  398. p1_inv.push(entity_gateway.create_item(
  399. item::NewItemEntity {
  400. item: item::ItemDetail::Weapon(
  401. item::weapon::Weapon {
  402. weapon: item::weapon::WeaponType::Raygun,
  403. grind: 5,
  404. special: Some(item::weapon::WeaponSpecial::Kings),
  405. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  406. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  407. None,],
  408. tekked: true,
  409. }
  410. ),
  411. }).await.unwrap());
  412. let equipped = item::EquippedEntity {
  413. weapon: Some(p1_inv[0].id),
  414. armor: None,
  415. shield: None,
  416. unit: [None; 4],
  417. mag: None,
  418. };
  419. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  420. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  421. let mut p2_inv = Vec::new();
  422. p2_inv.push(entity_gateway.create_item(
  423. item::NewItemEntity {
  424. item: item::ItemDetail::Weapon(
  425. item::weapon::Weapon {
  426. weapon: item::weapon::WeaponType::Raygun,
  427. grind: 5,
  428. special: Some(item::weapon::WeaponSpecial::Kings),
  429. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  430. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  431. None,],
  432. tekked: true,
  433. }
  434. ),
  435. }).await.unwrap());
  436. let equipped = item::EquippedEntity {
  437. weapon: Some(p2_inv[0].id),
  438. armor: None,
  439. shield: None,
  440. unit: [None; 4],
  441. mag: None,
  442. };
  443. entity_gateway.set_character_equips(&char2.id, &equipped).await.unwrap();
  444. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  445. let mut ship = Box::new(ShipServerState::builder()
  446. .gateway(entity_gateway.clone())
  447. .build());
  448. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  449. join_lobby(&mut ship, ClientId(1)).await;
  450. create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::VeryHard).await;
  451. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  452. join_lobby(&mut ship, ClientId(2)).await;
  453. join_room(&mut ship, ClientId(2), 0).await;
  454. let enemy_id = {
  455. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  456. let enemy_id = (0..).filter_map(|i| {
  457. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  458. if enemy.monster == MonsterType::Booma {
  459. Some(i)
  460. }
  461. else {
  462. None
  463. }
  464. })
  465. }).next().unwrap();
  466. enemy_id
  467. };
  468. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  469. client: 0,
  470. target: 0,
  471. client2: enemy_id as u8,
  472. target2: 16,
  473. enemy_id: enemy_id as u16,
  474. })))).await.unwrap().for_each(drop);
  475. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  476. client: 0,
  477. target: 0,
  478. client2: enemy_id as u8,
  479. target2: 16,
  480. enemy_id: enemy_id as u16,
  481. })))).await.unwrap().for_each(drop);
  482. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  483. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  484. println!("c1 exp: {:?}, c2 exp: {:?}", c1.character.exp, c2.character.exp);
  485. assert!(c1.character.exp == 80000010);
  486. assert!(c2.character.exp == 80000010);
  487. }
  488. #[async_std::test]
  489. async fn test_exp_steal_doesnt_exceed_100p() {
  490. assert!(false)
  491. }
  492. #[async_std::test]
  493. async fn test_exp_steal_multihit_penalty() {
  494. assert!(false)
  495. }
  496. #[async_std::test]
  497. async fn test_each_client_can_steal_exp_from_same_enemy() {
  498. assert!(false)
  499. }
  500. #[async_std::test]
  501. async fn test_cannot_steal_exp_from_boss() {
  502. assert!(false)
  503. }