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.

917 lines
33 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
3 years ago
3 years ago
3 years ago
3 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_multihit_penalty() {
  490. let mut entity_gateway = InMemoryGateway::default();
  491. let (_user1, mut char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  492. char1.exp = 80000000;
  493. char1.char_class = CharacterClass::HUcast;
  494. entity_gateway.save_character(&char1).await.unwrap();
  495. let mut p1_inv = Vec::new();
  496. p1_inv.push(entity_gateway.create_item(
  497. item::NewItemEntity {
  498. item: item::ItemDetail::Weapon(
  499. item::weapon::Weapon {
  500. weapon: item::weapon::WeaponType::Dagger,
  501. grind: 5,
  502. special: Some(item::weapon::WeaponSpecial::Kings),
  503. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  504. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  505. None,],
  506. tekked: true,
  507. }
  508. ),
  509. }).await.unwrap());
  510. p1_inv.push(entity_gateway.create_item(
  511. item::NewItemEntity {
  512. item: item::ItemDetail::Weapon(
  513. item::weapon::Weapon {
  514. weapon: item::weapon::WeaponType::Mechgun,
  515. grind: 5,
  516. special: Some(item::weapon::WeaponSpecial::Kings),
  517. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  518. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  519. None,],
  520. tekked: true,
  521. }
  522. ),
  523. }).await.unwrap());
  524. let equipped = item::EquippedEntity {
  525. weapon: Some(p1_inv[0].id),
  526. armor: None,
  527. shield: None,
  528. unit: [None; 4],
  529. mag: None,
  530. };
  531. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  532. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  533. let mut ship = Box::new(ShipServerState::builder()
  534. .gateway(entity_gateway.clone())
  535. .build());
  536. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  537. join_lobby(&mut ship, ClientId(1)).await;
  538. create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Ultimate).await;
  539. let enemy_id = {
  540. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  541. let enemy_id = (0..).filter_map(|i| {
  542. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  543. if enemy.monster == MonsterType::Booma {
  544. Some(i)
  545. }
  546. else {
  547. None
  548. }
  549. })
  550. }).next().unwrap();
  551. enemy_id
  552. };
  553. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  554. client: 0,
  555. target: 0,
  556. client2: enemy_id as u8,
  557. target2: 16,
  558. enemy_id: enemy_id as u16,
  559. })))).await.unwrap().for_each(drop);
  560. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  561. assert!(c1.character.exp == 80000040);
  562. // change equipped item
  563. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::PlayerEquipItem(PlayerEquipItem {
  564. client: 0,
  565. target: 0,
  566. item_id: 0x10001,
  567. sub_menu: 9,
  568. unknown1: 0,
  569. })))).await.unwrap().for_each(drop);
  570. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  571. client: 0,
  572. target: 0,
  573. client2: enemy_id as u8,
  574. target2: 16,
  575. enemy_id: enemy_id as u16,
  576. })))).await.unwrap().for_each(drop);
  577. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  578. assert!(c1.character.exp == 80000066);
  579. }
  580. #[async_std::test]
  581. async fn test_cannot_steal_exp_from_boss() {
  582. let mut entity_gateway = InMemoryGateway::default();
  583. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  584. let mut p1_inv = Vec::new();
  585. p1_inv.push(entity_gateway.create_item(
  586. item::NewItemEntity {
  587. item: item::ItemDetail::Weapon(
  588. item::weapon::Weapon {
  589. weapon: item::weapon::WeaponType::Raygun,
  590. grind: 5,
  591. special: Some(item::weapon::WeaponSpecial::Kings),
  592. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  593. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  594. None,],
  595. tekked: true,
  596. }
  597. ),
  598. }).await.unwrap());
  599. let equipped = item::EquippedEntity {
  600. weapon: Some(p1_inv[0].id),
  601. armor: None,
  602. shield: None,
  603. unit: [None; 4],
  604. mag: None,
  605. };
  606. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  607. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  608. let mut ship = Box::new(ShipServerState::builder()
  609. .gateway(entity_gateway.clone())
  610. .build());
  611. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  612. join_lobby(&mut ship, ClientId(1)).await;
  613. create_room(&mut ship, ClientId(1), "room", "").await;
  614. let enemy_id = {
  615. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  616. let enemy_id = (0..).filter_map(|i| {
  617. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  618. if enemy.monster == MonsterType::Dragon {
  619. Some(i)
  620. }
  621. else {
  622. None
  623. }
  624. })
  625. }).next().unwrap();
  626. enemy_id
  627. };
  628. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  629. client: 0,
  630. target: 0,
  631. client2: enemy_id as u8,
  632. target2: 16,
  633. enemy_id: enemy_id as u16,
  634. })))).await.unwrap().for_each(drop);
  635. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  636. assert!(c1.character.exp == 0);
  637. }
  638. #[async_std::test]
  639. async fn test_exp_steal_doesnt_exceed_100p() {
  640. let mut entity_gateway = InMemoryGateway::default();
  641. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  642. let mut p1_inv = Vec::new();
  643. p1_inv.push(entity_gateway.create_item(
  644. item::NewItemEntity {
  645. item: item::ItemDetail::Weapon(
  646. item::weapon::Weapon {
  647. weapon: item::weapon::WeaponType::Raygun,
  648. grind: 5,
  649. special: Some(item::weapon::WeaponSpecial::Kings),
  650. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  651. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  652. None,],
  653. tekked: true,
  654. }
  655. ),
  656. }).await.unwrap());
  657. let equipped = item::EquippedEntity {
  658. weapon: Some(p1_inv[0].id),
  659. armor: None,
  660. shield: None,
  661. unit: [None; 4],
  662. mag: None,
  663. };
  664. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  665. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  666. let mut ship = Box::new(ShipServerState::builder()
  667. .gateway(entity_gateway.clone())
  668. .build());
  669. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  670. join_lobby(&mut ship, ClientId(1)).await;
  671. create_room(&mut ship, ClientId(1), "room", "").await;
  672. let enemy_id = {
  673. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  674. let enemy_id = (0..).filter_map(|i| {
  675. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  676. if enemy.monster == MonsterType::Booma {
  677. Some(i)
  678. }
  679. else {
  680. None
  681. }
  682. })
  683. }).next().unwrap();
  684. enemy_id
  685. };
  686. for _ in 0..10 {
  687. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  688. client: 0,
  689. target: 0,
  690. client2: enemy_id as u8,
  691. target2: 16,
  692. enemy_id: enemy_id as u16,
  693. })))).await.unwrap().for_each(drop);
  694. }
  695. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  696. assert!(c1.character.exp == 5);
  697. }
  698. #[async_std::test]
  699. async fn test_each_client_can_steal_full_exp_from_same_enemy() {
  700. let mut entity_gateway = InMemoryGateway::default();
  701. let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await;
  702. let (_user2, char2) = new_user_character(&mut entity_gateway, "a2", "a", 1).await;
  703. entity_gateway.save_character(&char1).await.unwrap();
  704. entity_gateway.save_character(&char2).await.unwrap();
  705. let mut p1_inv = Vec::new();
  706. p1_inv.push(entity_gateway.create_item(
  707. item::NewItemEntity {
  708. item: item::ItemDetail::Weapon(
  709. item::weapon::Weapon {
  710. weapon: item::weapon::WeaponType::Raygun,
  711. grind: 5,
  712. special: Some(item::weapon::WeaponSpecial::Kings),
  713. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  714. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  715. None,],
  716. tekked: true,
  717. }
  718. ),
  719. }).await.unwrap());
  720. let equipped = item::EquippedEntity {
  721. weapon: Some(p1_inv[0].id),
  722. armor: None,
  723. shield: None,
  724. unit: [None; 4],
  725. mag: None,
  726. };
  727. entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap();
  728. entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(p1_inv)).await.unwrap();
  729. let mut p2_inv = Vec::new();
  730. p2_inv.push(entity_gateway.create_item(
  731. item::NewItemEntity {
  732. item: item::ItemDetail::Weapon(
  733. item::weapon::Weapon {
  734. weapon: item::weapon::WeaponType::Raygun,
  735. grind: 5,
  736. special: Some(item::weapon::WeaponSpecial::Kings),
  737. attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 100}),
  738. Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
  739. None,],
  740. tekked: true,
  741. }
  742. ),
  743. }).await.unwrap());
  744. let equipped = item::EquippedEntity {
  745. weapon: Some(p2_inv[0].id),
  746. armor: None,
  747. shield: None,
  748. unit: [None; 4],
  749. mag: None,
  750. };
  751. entity_gateway.set_character_equips(&char2.id, &equipped).await.unwrap();
  752. entity_gateway.set_character_inventory(&char2.id, &item::InventoryEntity::new(p2_inv)).await.unwrap();
  753. let mut ship = Box::new(ShipServerState::builder()
  754. .gateway(entity_gateway.clone())
  755. .build());
  756. log_in_char(&mut ship, ClientId(1), "a1", "a").await;
  757. join_lobby(&mut ship, ClientId(1)).await;
  758. create_room_with_difficulty(&mut ship, ClientId(1), "room", "", Difficulty::Normal).await;
  759. log_in_char(&mut ship, ClientId(2), "a2", "a").await;
  760. join_lobby(&mut ship, ClientId(2)).await;
  761. join_room(&mut ship, ClientId(2), 0).await;
  762. let enemy_id = {
  763. let room = ship.blocks.0[0].rooms[0].as_ref().unwrap();
  764. let enemy_id = (0..).filter_map(|i| {
  765. room.maps.enemy_by_id(i).ok().and_then(|enemy| {
  766. if enemy.monster == MonsterType::Booma {
  767. Some(i)
  768. }
  769. else {
  770. None
  771. }
  772. })
  773. }).next().unwrap();
  774. enemy_id
  775. };
  776. for _ in 0..10 {
  777. ship.handle(ClientId(1), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  778. client: 0,
  779. target: 0,
  780. client2: enemy_id as u8,
  781. target2: 16,
  782. enemy_id: enemy_id as u16,
  783. })))).await.unwrap().for_each(drop);
  784. ship.handle(ClientId(2), &RecvShipPacket::Message(Message::new(GameMessage::ExperienceSteal(ExperienceSteal{
  785. client: 0,
  786. target: 0,
  787. client2: enemy_id as u8,
  788. target2: 16,
  789. enemy_id: enemy_id as u16,
  790. })))).await.unwrap().for_each(drop);
  791. }
  792. let c1 = ship.clients.get(&ClientId(1)).unwrap();
  793. let c2 = ship.clients.get(&ClientId(2)).unwrap();
  794. println!("c1 exp: {:?}, c2 exp: {:?}", c1.character.exp, c2.character.exp);
  795. assert!(c1.character.exp == 5);
  796. assert!(c2.character.exp == 5);
  797. }