forked from NewEriduPubSec/JaneDoe-ZS
Compare commits
7 commits
436e691245
...
3043d45ac9
Author | SHA1 | Date | |
---|---|---|---|
|
3043d45ac9 | ||
|
05e8ef740d | ||
|
950a3725ea | ||
|
157832198c | ||
|
55780314d1 | ||
|
db2677be50 | ||
|
a7a1f4da37 |
61 changed files with 1074 additions and 197081 deletions
|
@ -13,8 +13,6 @@ tokio-util = { version = "0.7.10", features = ["io"] }
|
||||||
# Serialization
|
# Serialization
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
serde_json = "1.0.114"
|
serde_json = "1.0.114"
|
||||||
jsonc-parser = { version = "0.23.0", features = ["serde"] }
|
|
||||||
chrono = { version = "0.4.38", features = ["serde"] }
|
|
||||||
toml = "0.8.4"
|
toml = "0.8.4"
|
||||||
rbase64 = "2.0.3"
|
rbase64 = "2.0.3"
|
||||||
prost = "0.12.3"
|
prost = "0.12.3"
|
||||||
|
|
|
@ -6,13 +6,9 @@
|
||||||
### Current features
|
### Current features
|
||||||
- Logging in
|
- Logging in
|
||||||
- Fully playable prologue
|
- Fully playable prologue
|
||||||
- HollowDeepDive with Combat and Rally commissions
|
|
||||||
- Archive (playable cutscenes and battles)
|
|
||||||
- Open world
|
|
||||||
- World exploration with any character (can be changed with a command)
|
|
||||||
- Player progress saving with PostgreSQL
|
- Player progress saving with PostgreSQL
|
||||||
- Player management command system
|
- Unlock all characters
|
||||||
- Training
|
- Training battle
|
||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
- [Rust](https://www.rust-lang.org/tools/install)
|
- [Rust](https://www.rust-lang.org/tools/install)
|
||||||
|
|
|
@ -200,16 +200,5 @@
|
||||||
"store_template_id": 1191
|
"store_template_id": 1191
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
"event_id": 15000301,
|
|
||||||
"actions": [
|
|
||||||
{
|
|
||||||
"$type": "OpenUi",
|
|
||||||
"ui": "UINewsStandPageController",
|
|
||||||
"args": 0,
|
|
||||||
"store_template_id": 1061
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,212 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"ID": 100001,
|
|
||||||
"FOPDNLNNHDJ": 1000,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Arcade",
|
|
||||||
"EFPBDDJIJBO": "1040140114",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_RallyQuest.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_L.prefab",
|
|
||||||
"LDKNDDHOHND": "FF0019FF",
|
|
||||||
"EEBAIANJMEC": "006EFFFF|FF001900",
|
|
||||||
"EKMLECIKMID": false,
|
|
||||||
"FNIGJDFMHBA": "",
|
|
||||||
"BECFHCOGPKG": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100101,
|
|
||||||
"FOPDNLNNHDJ": 1001,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Story",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Story.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M.prefab",
|
|
||||||
"LDKNDDHOHND": "FF9500FF",
|
|
||||||
"EEBAIANJMEC": "FF9500FF|FFDE0000",
|
|
||||||
"EKMLECIKMID": false,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100102,
|
|
||||||
"FOPDNLNNHDJ": 1001,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_exploration",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Explore.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M02.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips03.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_03"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100103,
|
|
||||||
"FOPDNLNNHDJ": 1001,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_combat",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Combat.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_S.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips02.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100201,
|
|
||||||
"FOPDNLNNHDJ": 1002,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Story",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Story.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M.prefab",
|
|
||||||
"LDKNDDHOHND": "FF9500FF",
|
|
||||||
"EEBAIANJMEC": "FF9500FF|FFDE0000",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100202,
|
|
||||||
"FOPDNLNNHDJ": 1002,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_exploration",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Explore.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M02.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips03.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_03"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100203,
|
|
||||||
"FOPDNLNNHDJ": 1002,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_combat",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Combat.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_S.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips02.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100301,
|
|
||||||
"FOPDNLNNHDJ": 1003,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Story",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Story.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M.prefab",
|
|
||||||
"LDKNDDHOHND": "FF9500FF",
|
|
||||||
"EEBAIANJMEC": "FF9500FF|FFDE0000",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100302,
|
|
||||||
"FOPDNLNNHDJ": 1003,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_exploration",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Explore.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M02.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips03.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_03"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100303,
|
|
||||||
"FOPDNLNNHDJ": 1003,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_combat",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Combat.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_S.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips02.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100401,
|
|
||||||
"FOPDNLNNHDJ": 1004,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_BigWorld",
|
|
||||||
"EFPBDDJIJBO": "1100140008",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_HighRisk.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_L.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": false,
|
|
||||||
"FNIGJDFMHBA": "",
|
|
||||||
"BECFHCOGPKG": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100501,
|
|
||||||
"FOPDNLNNHDJ": 1005,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Story",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Story.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M.prefab",
|
|
||||||
"LDKNDDHOHND": "FF9500FF",
|
|
||||||
"EEBAIANJMEC": "FF9500FF|FFDE0000",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_01"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100502,
|
|
||||||
"FOPDNLNNHDJ": 1005,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_exploration",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Explore.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M02.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips03.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_03"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 100503,
|
|
||||||
"FOPDNLNNHDJ": 1005,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_combat",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Combat.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_S.prefab",
|
|
||||||
"LDKNDDHOHND": "00A1FFFF",
|
|
||||||
"EEBAIANJMEC": "00A1FFFF|00FFD300",
|
|
||||||
"EKMLECIKMID": true,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips02.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_02"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 109901,
|
|
||||||
"FOPDNLNNHDJ": 1099,
|
|
||||||
"DIIDBBGLDOL": "HollowGroupNameText_Story",
|
|
||||||
"EFPBDDJIJBO": "",
|
|
||||||
"OCBLGHECPLH": "Hollow_LockedHint_01",
|
|
||||||
"BEIEFNLAJCH": "UI/Sprite/A1DynamicLoad/YorozuyaPage/UnPacker/Icon_Story.png",
|
|
||||||
"CCFBKFKFJGM": "UI/3D/Yorozuya/Yorozuya_Hollow_Sphere_M.prefab",
|
|
||||||
"LDKNDDHOHND": "FF9500FF",
|
|
||||||
"EEBAIANJMEC": "FF9500FF|FFDE0000",
|
|
||||||
"EKMLECIKMID": false,
|
|
||||||
"FNIGJDFMHBA": "UI/Menus/Widget/Yorozuya/Icon_MapTips.prefab",
|
|
||||||
"BECFHCOGPKG": "YorozuyaMapTipsUnLockChange_01"
|
|
||||||
}
|
|
||||||
]
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,29 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"QuickAccessIndex": 1,
|
|
||||||
"QuickFuncID": 1005,
|
|
||||||
"RequiredUnlockIDs": [
|
|
||||||
1005
|
|
||||||
],
|
|
||||||
"EFPBDDJIJBO": 1040140154,
|
|
||||||
"BOKMLGNMJPB": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"QuickAccessIndex": 2,
|
|
||||||
"QuickFuncID": 1022,
|
|
||||||
"RequiredUnlockIDs": [
|
|
||||||
1022
|
|
||||||
],
|
|
||||||
"EFPBDDJIJBO": 1040140049,
|
|
||||||
"BOKMLGNMJPB": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"QuickAccessIndex": 3,
|
|
||||||
"QuickFuncID": 1009,
|
|
||||||
"RequiredUnlockIDs": [
|
|
||||||
1009
|
|
||||||
],
|
|
||||||
"EFPBDDJIJBO": 1050060115,
|
|
||||||
"BOKMLGNMJPB": null
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,112 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"BtnID": 1001,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1002,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1003,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1004,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1005,
|
|
||||||
"BOMNEKHOGIH": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnInterKnot.png",
|
|
||||||
"PECPFBBOGKO": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnInterKnot.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1006,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1007,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1008,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1009,
|
|
||||||
"BOMNEKHOGIH": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnGuide.png",
|
|
||||||
"PECPFBBOGKO": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnGuide.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1010,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1011,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1013,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1014,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1015,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1016,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1017,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1018,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1019,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1020,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1021,
|
|
||||||
"BOMNEKHOGIH": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnCamera.png",
|
|
||||||
"PECPFBBOGKO": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnCamera.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1022,
|
|
||||||
"BOMNEKHOGIH": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnMessage.png",
|
|
||||||
"PECPFBBOGKO": "UI/Sprite/A1DynamicLoad/MainCityMenus/Packer/BtnMessage.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"BtnID": 1023,
|
|
||||||
"BOMNEKHOGIH": "",
|
|
||||||
"PECPFBBOGKO": ""
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,882 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"AreaID": 500000101,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000001_1.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E2",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000102,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000001_2.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000103,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000001_3.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000201,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000002_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_B5",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000202,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000002_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000203,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000002_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000301,
|
|
||||||
"BattleEventID": 5000003,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000003_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_3_1",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000302,
|
|
||||||
"BattleEventID": 5000003,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000003_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_3_1",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000303,
|
|
||||||
"BattleEventID": 5000003,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000003_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_3_1",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000401,
|
|
||||||
"BattleEventID": 5000004,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000004_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_SpecialRoom_5",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000402,
|
|
||||||
"BattleEventID": 5000004,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000004_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_SpecialRoom_5",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_SP",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 500000403,
|
|
||||||
"BattleEventID": 5000004,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5000004_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_SpecialRoom_5",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_SP",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501010101,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010101_1.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501010102,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010101_2.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501010103,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010101_3.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501010104,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010101_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_22",
|
|
||||||
"LLPNKBBJHKL": "SpecialPlayerPos_1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501010105,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010101_5.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint5",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501011101,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010111_1.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Rain",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501011102,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010111_2.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "RallyPlayerPos_C1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Rain",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501011103,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010111_3.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "RallyPlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Rain",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501011104,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010111_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_22",
|
|
||||||
"LLPNKBBJHKL": "SpecialPlayerPos_1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "Rain",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501011105,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010111_5.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_F2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Rain",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501012101,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010121_1.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint6",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501012102,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010121_2.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint7",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501012103,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010121_3.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501012104,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010121_4.asset",
|
|
||||||
"MDMOGIDKCLG": "metro4_2_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020200,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_0.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_VR_TrainingRoom_30R",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020201,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint1",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020202,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint2",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020203,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020204,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint4",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020205,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_5.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint5",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020206,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_6.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_25_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint6",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020207,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_7.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint7",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020208,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_6.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_25_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint6",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501020209,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010201_9.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021101,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint1",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021102,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint2",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021103,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021104,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_12_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint4",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021105,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_5.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint5",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021106,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_6.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint6",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021107,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010211_7.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_5_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021301,
|
|
||||||
"BattleEventID": 5010213,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010213_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_B5",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021302,
|
|
||||||
"BattleEventID": 5010213,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010213_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021303,
|
|
||||||
"BattleEventID": 5010213,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010213_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501021304,
|
|
||||||
"BattleEventID": 5010213,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010213_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Boss",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "Thunder",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501022101,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010221_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint9",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501022102,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010221_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction3_4_SuccessiveLevel",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_C2",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501022103,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010221_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Zero",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_E4_Rally",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501022104,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010221_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Construction2_3_Zero",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_D4_Rally",
|
|
||||||
"TimePeriod": "Evening",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030101,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_3_Successive",
|
|
||||||
"LLPNKBBJHKL": "SpecialPlayerPos_B1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030102,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_2_1_Successive",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030103,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_2_1_Successive",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030104,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_2_1_Successive",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030105,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_5.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_2_1_Successive",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint4",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030106,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_6.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_15_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPointSideQuest1",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501030107,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010301_7.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_2_1_Successive",
|
|
||||||
"LLPNKBBJHKL": "SpecialRallyPos_7",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031101,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031102,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031103,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint3",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031104,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint4",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031105,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_5.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint5",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031106,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_6.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint6",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031107,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_7.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint7",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031108,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_8.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_Zero_ComplexRoom_15_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint8",
|
|
||||||
"TimePeriod": "Morning",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031109,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_9.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint9",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031110,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_10.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_1_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint10",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031111,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_11.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_2_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint11",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501031112,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010311_12.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_CheckPoint12",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501032101,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010321_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Zero",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A5_Rally",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501032102,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010321_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Zero",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A6_Rally",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501032103,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010321_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Zero",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_C5_Rally",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 501032104,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5010321_4.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_H_1_1_Rally",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_A1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": true,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503020101,
|
|
||||||
"BattleEventID": 5030201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030201_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_MetroArea_4_1_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503020102,
|
|
||||||
"BattleEventID": 5030201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030201_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_MetroArea_4_1_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503020103,
|
|
||||||
"BattleEventID": 5030201,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030201_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_MetroArea_4_1_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly3",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503021101,
|
|
||||||
"BattleEventID": 5030211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030211_1.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly1",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503021102,
|
|
||||||
"BattleEventID": 5030211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030211_2.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly2",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"AreaID": 503021103,
|
|
||||||
"BattleEventID": 5030211,
|
|
||||||
"NELIKCGAKEJ": "Level/FC_Main/FC_Successive/FC_5030211_3.asset",
|
|
||||||
"MDMOGIDKCLG": "Stage_SkyScraper_L_1_2_Lycaon",
|
|
||||||
"LLPNKBBJHKL": "PlayerPos_Ly3",
|
|
||||||
"TimePeriod": "Night",
|
|
||||||
"Weather": "SunShine",
|
|
||||||
"HAIGBCBDJPL": false,
|
|
||||||
"MBIMPLIHABC": ""
|
|
||||||
}
|
|
||||||
]
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,604 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"ID": 500000101,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea1Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000102,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea2Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000103,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea3Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000104,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea4Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000105,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea5Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000106,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "IsArea6Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000107,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "SideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000108,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "SecondSideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000109,
|
|
||||||
"BattleEventID": 5000001,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000201,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "whichAreaIn",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000202,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "IsArea2Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000203,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "IsArea3Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000204,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "IsArea4Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000205,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "IsArea5Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000206,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "SecretMission",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000207,
|
|
||||||
"BattleEventID": 5000002,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000301,
|
|
||||||
"BattleEventID": 5000003,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 500000401,
|
|
||||||
"BattleEventID": 5000004,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501010100,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501010101,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"VariableName": "SideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501010102,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501010103,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501010104,
|
|
||||||
"BattleEventID": 5010101,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011101,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011102,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "SideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011103,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011104,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011105,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "GroundSideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501011106,
|
|
||||||
"BattleEventID": 5010111,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501012101,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501012102,
|
|
||||||
"BattleEventID": 5010121,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020200,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsEnterTeachLevel",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020201,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea1Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020202,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea2Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020203,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea3Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020204,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea4Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020205,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea5Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020206,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea6Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020207,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea7Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020208,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "SideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020209,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsArea8Finish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020210,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "SecondSideQuest",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020211,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "StartSecondPhase",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020212,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020213,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020214,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020215,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501020216,
|
|
||||||
"BattleEventID": 5010201,
|
|
||||||
"VariableName": "LifeCoinGet",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021101,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021102,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021103,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021104,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021105,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "BossHealth",
|
|
||||||
"ValueType": "float",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021106,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "CargoCartStopped",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021107,
|
|
||||||
"BattleEventID": 5010211,
|
|
||||||
"VariableName": "IsLastAreaFinish",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501021301,
|
|
||||||
"BattleEventID": 5010213,
|
|
||||||
"VariableName": "whichAreaIn",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501022101,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501022102,
|
|
||||||
"BattleEventID": 5010221,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030101,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030102,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030103,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030104,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "DoorStatus1",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030105,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "DoorStatus2",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030106,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "DoorStatus3",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030107,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "DoorStatus4",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030108,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "DoorStatus5",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030109,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501030110,
|
|
||||||
"BattleEventID": 5010301,
|
|
||||||
"VariableName": "IsTrickFinish",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031101,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031102,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsSideQuestFinsih",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "false"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031103,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031104,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsAllyRescued",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031105,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsShortcutOpened",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031106,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsGuardDefeated",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031107,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "DoorStatus1",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031108,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "DoorStatus2",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031109,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "DoorStatus3",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031110,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "DoorStatus4",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031111,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "DoorStatus5",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031112,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsAllyImposterCatched",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031113,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "IsSideQuestRestart",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501031114,
|
|
||||||
"BattleEventID": 5010311,
|
|
||||||
"VariableName": "LifeCoinGet",
|
|
||||||
"ValueType": "bool",
|
|
||||||
"InitialValue": "FALSE"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501032101,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "4"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 501032102,
|
|
||||||
"BattleEventID": 5010321,
|
|
||||||
"VariableName": "RevivedTime",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 503020101,
|
|
||||||
"BattleEventID": 5030201,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": 503021101,
|
|
||||||
"BattleEventID": 5030211,
|
|
||||||
"VariableName": "AreaSelect",
|
|
||||||
"ValueType": "int",
|
|
||||||
"InitialValue": "1"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -168,7 +168,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Bangboo": {
|
"Standard:Bangboo": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_BANGBOO",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
54002, // 阿全
|
54002, // 阿全
|
||||||
54005, // 艾米莉安
|
54005, // 艾米莉安
|
||||||
|
@ -181,7 +180,6 @@
|
||||||
"category_weight": 1
|
"category_weight": 1
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Bangboo": {
|
"Event-Exclusive:Bangboo": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_BANGBOO",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
54004, // 巴特勒
|
54004, // 巴特勒
|
||||||
],
|
],
|
||||||
|
@ -201,7 +199,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Bangboo": {
|
"Standard:Bangboo": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_BANGBOO",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
53001, // 企鹅布
|
53001, // 企鹅布
|
||||||
53003, // 寻宝布
|
53003, // 寻宝布
|
||||||
|
@ -227,7 +224,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -271,7 +267,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1021, // 猫又
|
1021, // 猫又
|
||||||
1101, // 珂蕾妲
|
1101, // 珂蕾妲
|
||||||
|
@ -283,7 +278,6 @@
|
||||||
"category_weight": 50
|
"category_weight": 50
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1191, // 艾莲
|
1191, // 艾莲
|
||||||
|
@ -306,7 +300,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -319,7 +312,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1111, // 安东
|
1111, // 安东
|
||||||
|
@ -328,7 +320,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -361,7 +352,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -408,7 +398,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14102, // 钢铁肉垫
|
14102, // 钢铁肉垫
|
||||||
14110, // 燃狱齿轮
|
14110, // 燃狱齿轮
|
||||||
|
@ -420,7 +409,6 @@
|
||||||
"category_weight": 25
|
"category_weight": 25
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14119, // 深海访客
|
14119, // 深海访客
|
||||||
],
|
],
|
||||||
|
@ -445,7 +433,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -460,7 +447,6 @@
|
||||||
"category_weight": 3750
|
"category_weight": 3750
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -482,7 +468,6 @@
|
||||||
"category_weight": 13125
|
"category_weight": 13125
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13113, // 含羞恶面
|
13113, // 含羞恶面
|
||||||
13111, // 旋钻机-赤轴
|
13111, // 旋钻机-赤轴
|
||||||
|
@ -500,7 +485,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -544,7 +528,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1021, // 猫又
|
1021, // 猫又
|
||||||
1101, // 珂蕾妲
|
1101, // 珂蕾妲
|
||||||
|
@ -556,7 +539,6 @@
|
||||||
"category_weight": 50
|
"category_weight": 50
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1241 // 朱鸢
|
1241 // 朱鸢
|
||||||
|
@ -576,7 +558,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1061, // 可琳
|
1061, // 可琳
|
||||||
|
@ -589,7 +570,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -598,7 +578,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -631,7 +610,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -675,7 +653,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14102, // 钢铁肉垫
|
14102, // 钢铁肉垫
|
||||||
14110, // 燃狱齿轮
|
14110, // 燃狱齿轮
|
||||||
|
@ -687,7 +664,6 @@
|
||||||
"category_weight": 25
|
"category_weight": 25
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14124 // 防暴者VI型
|
14124 // 防暴者VI型
|
||||||
],
|
],
|
||||||
|
@ -707,7 +683,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -722,7 +697,6 @@
|
||||||
"category_weight": 3750
|
"category_weight": 3750
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13007, // 正版变身器
|
13007, // 正版变身器
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -744,7 +718,6 @@
|
||||||
"category_weight": 13125
|
"category_weight": 13125
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13103, // 聚宝箱
|
13103, // 聚宝箱
|
||||||
13112, // 比格气缸
|
13112, // 比格气缸
|
||||||
|
@ -762,7 +735,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -808,7 +780,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1021, // 猫又
|
1021, // 猫又
|
||||||
1101, // 珂蕾妲
|
1101, // 珂蕾妲
|
||||||
|
@ -820,7 +791,6 @@
|
||||||
"category_weight": 50
|
"category_weight": 50
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1251, // 青衣
|
1251, // 青衣
|
||||||
|
@ -840,7 +810,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -854,7 +823,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1131, // 苍角
|
1131, // 苍角
|
||||||
|
@ -863,7 +831,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -897,7 +864,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -941,7 +907,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14102, // 钢铁肉垫
|
14102, // 钢铁肉垫
|
||||||
14110, // 燃狱齿轮
|
14110, // 燃狱齿轮
|
||||||
|
@ -953,7 +918,6 @@
|
||||||
"category_weight": 25
|
"category_weight": 25
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14125, // 玉壶青冰
|
14125, // 玉壶青冰
|
||||||
],
|
],
|
||||||
|
@ -973,7 +937,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -986,7 +949,6 @@
|
||||||
"category_weight": 3750
|
"category_weight": 3750
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -1009,7 +971,6 @@
|
||||||
"category_weight": 13125
|
"category_weight": 13125
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13113, // 含羞恶面
|
13113, // 含羞恶面
|
||||||
13127, // 维序者-特化型
|
13127, // 维序者-特化型
|
||||||
|
@ -1027,7 +988,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -1071,7 +1031,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1021, // 猫又
|
1021, // 猫又
|
||||||
1101, // 珂蕾妲
|
1101, // 珂蕾妲
|
||||||
|
@ -1083,7 +1042,6 @@
|
||||||
"category_weight": 50
|
"category_weight": 50
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1261, // 简
|
1261, // 简
|
||||||
|
@ -1103,7 +1061,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -1117,7 +1074,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Event-Exclusive:Agent": {
|
"Event-Exclusive:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"is_promotional_items": true,
|
"is_promotional_items": true,
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1271, // 赛斯
|
1271, // 赛斯
|
||||||
|
@ -1126,7 +1082,6 @@
|
||||||
"category_weight": 3525
|
"category_weight": 3525
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -1160,7 +1115,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
@ -1204,7 +1158,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14102, // 钢铁肉垫
|
14102, // 钢铁肉垫
|
||||||
14110, // 燃狱齿轮
|
14110, // 燃狱齿轮
|
||||||
|
@ -1216,7 +1169,6 @@
|
||||||
"category_weight": 25
|
"category_weight": 25
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
14126, // 淬锋钳刺
|
14126, // 淬锋钳刺
|
||||||
],
|
],
|
||||||
|
@ -1236,7 +1188,6 @@
|
||||||
],
|
],
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:Agent": {
|
"Standard:Agent": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
1011, // 安比
|
1011, // 安比
|
||||||
1031, // 妮可
|
1031, // 妮可
|
||||||
|
@ -1249,7 +1200,6 @@
|
||||||
"category_weight": 3750
|
"category_weight": 3750
|
||||||
},
|
},
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13001, // 街头巨星
|
13001, // 街头巨星
|
||||||
13002, // 时光切片
|
13002, // 时光切片
|
||||||
|
@ -1272,7 +1222,6 @@
|
||||||
"category_weight": 13125
|
"category_weight": 13125
|
||||||
},
|
},
|
||||||
"Event-Exclusive:W-Engine": {
|
"Event-Exclusive:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
13127, // 维序者-特化型
|
13127, // 维序者-特化型
|
||||||
13113, // 含羞恶面
|
13113, // 含羞恶面
|
||||||
|
@ -1290,7 +1239,6 @@
|
||||||
"probability_model_tag": "get-B",
|
"probability_model_tag": "get-B",
|
||||||
"categories": {
|
"categories": {
|
||||||
"Standard:W-Engine": {
|
"Standard:W-Engine": {
|
||||||
"item_type": "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
"item_ids": [
|
"item_ids": [
|
||||||
12001, // 「月相」-望
|
12001, // 「月相」-望
|
||||||
12002, // 「月相」-晦
|
12002, // 「月相」-晦
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
pub const SERVER_VERSION: &str = "0.2.0";
|
pub const SERVER_VERSION: &str = "0.1.0";
|
||||||
pub const CLIENT_VERSION: &str = "CNBeta1.1.1";
|
pub const CLIENT_VERSION: &str = "CNBeta1.1.1";
|
||||||
|
|
|
@ -7,8 +7,6 @@ version.workspace = true
|
||||||
# Serialization
|
# Serialization
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
jsonc-parser.workspace = true
|
|
||||||
chrono.workspace = true
|
|
||||||
prost.workspace = true
|
prost.workspace = true
|
||||||
|
|
||||||
# Util
|
# Util
|
||||||
|
@ -20,3 +18,5 @@ tracing.workspace = true
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
proto.workspace = true
|
proto.workspace = true
|
||||||
|
jsonc-parser = { version = "0.23.0", features = ["serde"] }
|
||||||
|
chrono = { version = "0.4.38", features = ["serde"] }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use chrono::{prelude::Local, DateTime};
|
use chrono::{prelude::Local, DateTime};
|
||||||
|
use proto::GachaAddedItemType;
|
||||||
use serde::{Deserialize, Deserializer};
|
use serde::{Deserialize, Deserializer};
|
||||||
use tracing;
|
use tracing;
|
||||||
|
|
||||||
|
@ -151,64 +152,13 @@ impl DiscountPolicyCollection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub enum GachaAddedItemType {
|
|
||||||
#[default]
|
|
||||||
None = 0,
|
|
||||||
Weapon = 1,
|
|
||||||
Character = 2,
|
|
||||||
Bangboo = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GachaAddedItemType {
|
|
||||||
pub fn as_str_name(&self) -> &'static str {
|
|
||||||
match self {
|
|
||||||
GachaAddedItemType::None => "GACHA_ADDED_ITEM_TYPE_NONE",
|
|
||||||
GachaAddedItemType::Weapon => "GACHA_ADDED_ITEM_TYPE_WEAPON",
|
|
||||||
GachaAddedItemType::Character => "GACHA_ADDED_ITEM_TYPE_CHARACTER",
|
|
||||||
GachaAddedItemType::Bangboo => "GACHA_ADDED_ITEM_TYPE_BANGBOO",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
|
|
||||||
match value {
|
|
||||||
"GACHA_ADDED_ITEM_TYPE_NONE" => Some(Self::None),
|
|
||||||
"GACHA_ADDED_ITEM_TYPE_WEAPON" => Some(Self::Weapon),
|
|
||||||
"GACHA_ADDED_ITEM_TYPE_CHARACTER" => Some(Self::Character),
|
|
||||||
"GACHA_ADDED_ITEM_TYPE_BANGBOO" => Some(Self::Bangboo),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<i32> for GachaAddedItemType {
|
|
||||||
fn from(value: i32) -> Self {
|
|
||||||
match value {
|
|
||||||
1 => Self::Weapon,
|
|
||||||
2 => Self::Character,
|
|
||||||
3 => Self::Bangboo,
|
|
||||||
_ => Self::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<i32> for GachaAddedItemType {
|
|
||||||
fn into(self) -> i32 {
|
|
||||||
match self {
|
|
||||||
Self::Weapon => 1,
|
|
||||||
Self::Character => 2,
|
|
||||||
Self::Bangboo => 3,
|
|
||||||
Self::None => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
pub struct GachaCategoryInfo {
|
pub struct GachaCategoryInfo {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub is_promotional_items: bool,
|
pub is_promotional_items: bool,
|
||||||
pub item_ids: Vec<u32>,
|
pub item_ids: Vec<u32>,
|
||||||
pub category_weight: u32,
|
pub category_weight: u32,
|
||||||
#[serde(deserialize_with = "from_str")]
|
#[serde(default, deserialize_with = "from_str")]
|
||||||
pub item_type: GachaAddedItemType,
|
pub item_type: GachaAddedItemType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::BattleEventConfigID;
|
|
||||||
|
|
||||||
template_id!(ArchiveBattleQuest u32 id);
|
template_id!(ArchiveBattleQuest u32 id);
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -21,7 +19,7 @@ pub struct ArchiveBattleQuestTemplate {
|
||||||
#[serde(rename = "FirstBattleEventID")]
|
#[serde(rename = "FirstBattleEventID")]
|
||||||
pub first_battle_event_id: u32,
|
pub first_battle_event_id: u32,
|
||||||
#[serde(rename = "BattleEventID")]
|
#[serde(rename = "BattleEventID")]
|
||||||
pub battle_event_id: BattleEventConfigID,
|
pub battle_event_id: u32,
|
||||||
pub battle_rank: String,
|
pub battle_rank: String,
|
||||||
pub slot1_avatar: i32,
|
pub slot1_avatar: i32,
|
||||||
pub slot2_avatar: i32,
|
pub slot2_avatar: i32,
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use super::OnceRewardID;
|
|
||||||
|
|
||||||
template_id!(BattleEventConfig u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct BattleEventConfigTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: BattleEventConfigID,
|
|
||||||
#[serde(rename = "LevelDesignID")]
|
|
||||||
pub level_design_id: u32,
|
|
||||||
pub normal_drop: String,
|
|
||||||
pub special_drop: Vec<OnceRewardID>,
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use super::BattleEventConfigID;
|
|
||||||
|
|
||||||
template_id!(BattleGroupConfig u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct BattleGroupConfigTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: BattleGroupConfigID,
|
|
||||||
#[serde(rename = "QuestID")]
|
|
||||||
pub quest_id: u32,
|
|
||||||
#[serde(rename = "BattleEventID")]
|
|
||||||
pub battle_event_id: BattleEventConfigID,
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(HollowConfig u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct HollowConfigTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: HollowConfigID,
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(HollowQuest u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct HollowQuestTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: HollowQuestID,
|
|
||||||
#[serde(rename = "ChessBoardID")]
|
|
||||||
pub chess_board_id: u32,
|
|
||||||
pub hollow_quest_type: u32,
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(Item u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct ItemTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: ItemID,
|
|
||||||
}
|
|
|
@ -87,15 +87,4 @@ template_tables! {
|
||||||
MainCityBgmConfigTemplate;
|
MainCityBgmConfigTemplate;
|
||||||
ArchiveFileQuestTemplate;
|
ArchiveFileQuestTemplate;
|
||||||
ArchiveBattleQuestTemplate;
|
ArchiveBattleQuestTemplate;
|
||||||
HollowQuestTemplate;
|
|
||||||
HollowConfigTemplate;
|
|
||||||
BattleEventConfigTemplate;
|
|
||||||
BattleGroupConfigTemplate;
|
|
||||||
SubAreaDataTemplate;
|
|
||||||
VariableDataTemplate;
|
|
||||||
OnceRewardTemplate;
|
|
||||||
QuickAccessTemplate;
|
|
||||||
QuickFuncTemplate;
|
|
||||||
TeleportConfigTemplate;
|
|
||||||
ItemTemplate;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(OnceReward u32 reward_id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct OnceRewardTemplate {
|
|
||||||
#[serde(rename = "RewardID")]
|
|
||||||
pub reward_id: OnceRewardID,
|
|
||||||
pub reward_list: Vec<RewardItem>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct RewardItem {
|
|
||||||
#[serde(rename = "RewardItemID")]
|
|
||||||
pub reward_item_id: u32,
|
|
||||||
pub reward_amount: u32,
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(QuickAccess u32 quick_func_id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct QuickAccessTemplate {
|
|
||||||
pub quick_access_index: u32,
|
|
||||||
#[serde(rename = "QuickFuncID")]
|
|
||||||
pub quick_func_id: QuickAccessID,
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(QuickFunc u32 btn_id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct QuickFuncTemplate {
|
|
||||||
#[serde(rename = "BtnID")]
|
|
||||||
pub btn_id: QuickFuncID,
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
use std::u32;
|
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(SubAreaData u32 area_id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct SubAreaDataTemplate {
|
|
||||||
#[serde(rename = "AreaID")]
|
|
||||||
pub area_id: SubAreaDataID,
|
|
||||||
#[serde(rename = "BattleEventID")]
|
|
||||||
pub battle_event_id: u32,
|
|
||||||
pub time_period: String,
|
|
||||||
pub weather: String,
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(TeleportConfig i32 teleport_id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct TeleportConfigTemplate {
|
|
||||||
#[serde(rename = "TeleportID")]
|
|
||||||
pub teleport_id: TeleportConfigID,
|
|
||||||
pub client_visible: u32,
|
|
||||||
}
|
|
|
@ -1,7 +1,5 @@
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::BattleEventConfigID;
|
|
||||||
|
|
||||||
template_id!(TrainingQuest u32 id);
|
template_id!(TrainingQuest u32 id);
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -9,5 +7,5 @@ template_id!(TrainingQuest u32 id);
|
||||||
pub struct TrainingQuestTemplate {
|
pub struct TrainingQuestTemplate {
|
||||||
pub id: TrainingQuestID,
|
pub id: TrainingQuestID,
|
||||||
pub training_type: u32,
|
pub training_type: u32,
|
||||||
pub battle_event_id: BattleEventConfigID,
|
pub battle_event_id: u32,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
use std::u32;
|
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
template_id!(VariableData u32 id);
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
#[serde(rename_all = "PascalCase")]
|
|
||||||
pub struct VariableDataTemplate {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: VariableDataID,
|
|
||||||
#[serde(rename = "BattleEventID")]
|
|
||||||
pub battle_event_id: u32,
|
|
||||||
pub variable_name: String,
|
|
||||||
pub value_type: VariableValueType,
|
|
||||||
pub initial_value: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum VariableValueType {
|
|
||||||
Int,
|
|
||||||
Bool,
|
|
||||||
Float,
|
|
||||||
}
|
|
|
@ -15,7 +15,6 @@ rbase64.workspace = true
|
||||||
toml.workspace = true
|
toml.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
serde_json.workspace = true
|
serde_json.workspace = true
|
||||||
chrono.workspace = true
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
sqlx.workspace = true
|
sqlx.workspace = true
|
||||||
|
@ -42,3 +41,4 @@ tracing-bunyan-formatter.workspace = true
|
||||||
common.workspace = true
|
common.workspace = true
|
||||||
data.workspace = true
|
data.workspace = true
|
||||||
proto.workspace = true
|
proto.workspace = true
|
||||||
|
chrono = { version = "0.4.38", features = ["serde"] }
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::logic::{EOperator, ESystem};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use data::tables::{self, QuickFuncID};
|
use data::tables;
|
||||||
|
|
||||||
pub async fn on_get_tips_info(
|
pub async fn on_get_tips_info(
|
||||||
_session: &NetSession,
|
_session: &NetSession,
|
||||||
|
@ -21,34 +21,23 @@ pub async fn on_get_client_systems_info(
|
||||||
player: &mut Player,
|
player: &mut Player,
|
||||||
_req: GetClientSystemsInfoCsReq,
|
_req: GetClientSystemsInfoCsReq,
|
||||||
) -> NetResult<GetClientSystemsInfoScRsp> {
|
) -> NetResult<GetClientSystemsInfoScRsp> {
|
||||||
let mut post_girl_data = PostGirlData {
|
|
||||||
post_girl_list: tables::post_girl_config_template_tb::iter()
|
|
||||||
.map(|template| PostGirlItem {
|
|
||||||
template_id: template.id.value(),
|
|
||||||
unlock_time: 1720052644,
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
if let Some(post_girl_id) = player.basic_data_model.selected_post_girl_id {
|
|
||||||
post_girl_data
|
|
||||||
.selected_post_girl_id_list
|
|
||||||
.push(post_girl_id.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(GetClientSystemsInfoScRsp {
|
Ok(GetClientSystemsInfoScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
info: Some(ClientSystemsInfo {
|
info: Some(ClientSystemsInfo {
|
||||||
post_girl_data: Some(post_girl_data),
|
post_girl_data: Some(PostGirlData {
|
||||||
unlock_data: Some(player.lock_model.to_client()),
|
selected_post_girl_id_list: tables::post_girl_config_template_tb::iter()
|
||||||
calling_card_data: Some(CallingCardData::default()),
|
.map(|template| template.id.value())
|
||||||
teleport_data: Some(TeleportData {
|
.collect(),
|
||||||
unlock_id_list: tables::teleport_config_template_tb::iter()
|
post_girl_list: tables::post_girl_config_template_tb::iter()
|
||||||
.filter(|template| template.client_visible > 0)
|
.map(|template| PostGirlItem {
|
||||||
.map(|template| template.teleport_id.value())
|
template_id: template.id.value(),
|
||||||
|
unlock_time: 1000,
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
|
unlock_data: Some(player.lock_model.to_client()),
|
||||||
|
hbhfjgbahgf: Some(Aboegnnepmi::default()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -65,16 +54,6 @@ pub async fn on_get_news_stand_data(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_news_stand_seen(
|
|
||||||
_session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: NewsStandSeenCsReq,
|
|
||||||
) -> NetResult<NewsStandSeenScRsp> {
|
|
||||||
Ok(NewsStandSeenScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn on_get_trashbin_hermit_data(
|
pub async fn on_get_trashbin_hermit_data(
|
||||||
_session: &NetSession,
|
_session: &NetSession,
|
||||||
_player: &mut Player,
|
_player: &mut Player,
|
||||||
|
@ -194,70 +173,3 @@ pub async fn on_interact_with_scene_object(
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_mod_quick_menu(
|
|
||||||
_session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: ModQuickMenuCsReq,
|
|
||||||
) -> NetResult<ModQuickMenuScRsp> {
|
|
||||||
let mut quick_access_data_list: Vec<QuickAccessData> = vec![];
|
|
||||||
for data in _req.quick_access_data_list.iter() {
|
|
||||||
quick_access_data_list.push(
|
|
||||||
_player
|
|
||||||
.lock_model
|
|
||||||
.mod_quick_access(data.quick_access_index, QuickFuncID::new(data.btn_id)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_session
|
|
||||||
.notify(PlayerSyncScNotify {
|
|
||||||
client_systems_sync: Some(ClientSystemsSync {
|
|
||||||
quick_access_data_list: _player.lock_model.quick_access_to_client(),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(ModQuickMenuScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn on_change_post_girl(
|
|
||||||
_session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: ChangePostGirlCsReq,
|
|
||||||
) -> NetResult<ChangePostGirlScRsp> {
|
|
||||||
if _req.new_selected_post_girl_id_list.len() != 1 {
|
|
||||||
return Ok(ChangePostGirlScRsp {
|
|
||||||
retcode: Retcode::RetFail.into(),
|
|
||||||
..Default::default()
|
|
||||||
});
|
|
||||||
};
|
|
||||||
match tables::PostGirlConfigID::new(*_req.new_selected_post_girl_id_list.get(0).unwrap()) {
|
|
||||||
Some(post_girl_id) => {
|
|
||||||
_player.basic_data_model.selected_post_girl_id = Some(post_girl_id);
|
|
||||||
_session
|
|
||||||
.notify(PlayerSyncScNotify {
|
|
||||||
client_systems_sync: Some(ClientSystemsSync {
|
|
||||||
post_girl_data: Some(PostGirlSync {
|
|
||||||
selected_post_girl_id_list: vec![post_girl_id.value()],
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
Ok(ChangePostGirlScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => Ok(ChangePostGirlScRsp {
|
|
||||||
retcode: Retcode::RetFail.into(),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
use data::{
|
use std::{
|
||||||
gacha::{
|
cmp::min,
|
||||||
gacha_config::{CharacterGachaPool, GachaAddedItemType},
|
collections::{
|
||||||
global_gacha_config,
|
hash_map::Entry::{Occupied, Vacant},
|
||||||
|
HashSet,
|
||||||
},
|
},
|
||||||
tables::{AvatarBaseID, ItemID, WeaponID},
|
|
||||||
};
|
};
|
||||||
use proto::{GainItemInfo, GetGachaDataScRsp};
|
|
||||||
|
use data::{
|
||||||
|
gacha::{gacha_config::*, global_gacha_config},
|
||||||
|
tables::{AvatarBaseID, WeaponID},
|
||||||
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
|
||||||
handlers::core::NetError,
|
|
||||||
logic::{item::ItemModel, role::RoleModel},
|
|
||||||
};
|
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
pub async fn on_get_gacha_data(
|
pub async fn on_get_gacha_data(
|
||||||
_session: &NetSession,
|
_session: &NetSession,
|
||||||
|
@ -31,7 +32,7 @@ pub async fn on_get_gacha_data(
|
||||||
Ok(GetGachaDataScRsp {
|
Ok(GetGachaDataScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
gacha_type: req.gacha_type,
|
gacha_type: req.gacha_type,
|
||||||
gacha_data: Some(_player.gacha_model.to_client(&Local::now())),
|
gacha_data: Some(generate_all_gacha_info(_player, &Local::now())),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,58 +51,101 @@ pub async fn on_do_gacha(
|
||||||
&gachaconf.character_gacha_pool_list,
|
&gachaconf.character_gacha_pool_list,
|
||||||
&req.gacha_parent_schedule_id,
|
&req.gacha_parent_schedule_id,
|
||||||
&pull_time,
|
&pull_time,
|
||||||
)?;
|
);
|
||||||
|
if let None = target_pool {
|
||||||
|
tracing::info!(
|
||||||
|
"refuse gacha because: pool of parent_schedule_id {} not found",
|
||||||
|
req.gacha_parent_schedule_id
|
||||||
|
);
|
||||||
|
return Ok(DoGachaScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let target_pool = target_pool.unwrap();
|
||||||
|
|
||||||
// tracing::info!("cost_item_count: {}", req.cost_item_count);
|
// tracing::info!("cost_item_count: {}", req.cost_item_count);
|
||||||
let pull_count = if req.cost_item_count > 1 { 10 } else { 1 };
|
let mut pull_count = if req.cost_item_count > 1 { 10 } else { 1 };
|
||||||
let mut cost_count = gacha_model.get_actual_cost_count(target_pool, &pull_count);
|
let mut cost_count = pull_count;
|
||||||
if pull_count != req.cost_item_count {
|
|
||||||
|
if pull_count == 10 {
|
||||||
|
let discount_tag = &gachaconf.common_properties.ten_pull_discount_tag;
|
||||||
|
if target_pool.discount_policy_tags.contains(&discount_tag) {
|
||||||
|
let gacha_bin = &mut gacha_model.gacha_bin;
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
let discount_policy = gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.ten_pull_discount_map
|
||||||
|
.get(discount_tag)
|
||||||
|
.unwrap();
|
||||||
|
let usage = status_bin.discount_usage_map.get_mut(discount_tag).unwrap();
|
||||||
|
if *usage < discount_policy.use_limit {
|
||||||
|
*usage += 1;
|
||||||
|
// cost_count = discount_policy.discounted_prize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cost_count != req.cost_item_count {
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"refuse gacha because: expected cost item {cost_count}, found {}",
|
"refuse gacha because: expected cost item {cost_count}, found {}",
|
||||||
req.cost_item_count
|
req.cost_item_count
|
||||||
);
|
);
|
||||||
return Err(NetError::from(Retcode::RetFail));
|
return Ok(DoGachaScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// TODO: cost resource
|
// TODO: cost resource
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut gain_item_list: Vec<GainItemInfo> = vec![];
|
let mut gain_item_list: Vec<GainItemInfo> = vec![];
|
||||||
while cost_count > 0 {
|
while pull_count > 0 {
|
||||||
let pull_result = gacha_model.perform_pull_pool(&pull_time, target_pool);
|
let pull_result = gacha_model.perform_pull_pool(&pull_time, target_pool);
|
||||||
|
let extra_item_bin = pull_result.extra_item_bin.clone().unwrap();
|
||||||
let uid = add_item(
|
let uid = match GachaAddedItemType::try_from(pull_result.item_type) {
|
||||||
role_model,
|
Ok(enum_val) => match enum_val {
|
||||||
item_model,
|
GachaAddedItemType::Weapon => match WeaponID::new(pull_result.obtained_item_id) {
|
||||||
&pull_result.obtained_item_id,
|
Some(id) => item_model.add_weapon(id).value(),
|
||||||
&pull_result.item_type,
|
None => 0,
|
||||||
)?;
|
},
|
||||||
let (mut extra_item_id, mut extra_item_count) = (0, 0);
|
GachaAddedItemType::Character => {
|
||||||
if let Some(extra_resources) = &pull_result.extra_resources {
|
match AvatarBaseID::new(pull_result.obtained_item_id) {
|
||||||
(extra_item_id, extra_item_count) = (
|
Some(id) => {
|
||||||
extra_resources.extra_item_id.value(),
|
role_model.add_avatar(id);
|
||||||
extra_resources.extra_item_count.clone(),
|
0
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => 0,
|
||||||
|
},
|
||||||
|
Err(_err) => 0,
|
||||||
|
};
|
||||||
|
if extra_item_bin.extra_item_id != 0 {
|
||||||
|
item_model.add_resource(
|
||||||
|
extra_item_bin.extra_item_id,
|
||||||
|
extra_item_bin.extra_item_count,
|
||||||
);
|
);
|
||||||
item_model.add_resource(extra_item_id, extra_item_count);
|
|
||||||
}
|
}
|
||||||
gain_item_list.push(GainItemInfo {
|
gain_item_list.push(GainItemInfo {
|
||||||
item_id: pull_result.obtained_item_id.value(),
|
item_id: pull_result.obtained_item_id,
|
||||||
extra_item_id,
|
extra_item_id: extra_item_bin.extra_item_id,
|
||||||
extra_item_count,
|
extra_item_count: extra_item_bin.extra_item_count,
|
||||||
uid,
|
uid,
|
||||||
num: 1,
|
num: 1,
|
||||||
..GainItemInfo::default()
|
..GainItemInfo::default()
|
||||||
});
|
});
|
||||||
cost_count -= 1;
|
pull_count -= 1;
|
||||||
gacha_model.gacha_records.push(pull_result);
|
gacha_model.gacha_bin.gacha_records.push(pull_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
_session
|
|
||||||
.notify(construct_sync(role_model, item_model))
|
|
||||||
.await?;
|
|
||||||
Ok(DoGachaScRsp {
|
Ok(DoGachaScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
gain_item_list,
|
gain_item_list,
|
||||||
gacha_data: Some(gacha_model.to_client(&pull_time)),
|
gacha_data: Some(generate_all_gacha_info(_player, &pull_time)),
|
||||||
cost_item_count: req.cost_item_count,
|
cost_item_count: req.cost_item_count,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -114,29 +158,122 @@ pub async fn on_gacha_free_agent(
|
||||||
let gachaconf = global_gacha_config();
|
let gachaconf = global_gacha_config();
|
||||||
let gacha_model = &mut _player.gacha_model;
|
let gacha_model = &mut _player.gacha_model;
|
||||||
let role_model = &mut _player.role_model;
|
let role_model = &mut _player.role_model;
|
||||||
let item_model = &mut _player.item_model;
|
|
||||||
let pull_time = Local::now();
|
let pull_time = Local::now();
|
||||||
let target_pool = get_gacha_pool(
|
let target_pool = get_gacha_pool(
|
||||||
&gachaconf.character_gacha_pool_list,
|
&gachaconf.character_gacha_pool_list,
|
||||||
&req.gacha_parent_schedule_id,
|
&req.gacha_parent_schedule_id,
|
||||||
&pull_time,
|
&pull_time,
|
||||||
)?;
|
);
|
||||||
|
if let None = target_pool {
|
||||||
|
tracing::info!(
|
||||||
|
"refuse free agent because: pool of parent_schedule_id {} not found",
|
||||||
|
req.gacha_parent_schedule_id
|
||||||
|
);
|
||||||
|
return Ok(GachaFreeAgentScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let target_pool = target_pool.unwrap();
|
||||||
|
let gacha_bin = &mut _player.gacha_model.gacha_bin;
|
||||||
|
let sharing_guarantee_category_tag = &target_pool.sharing_guarantee_info_category;
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(sharing_guarantee_category_tag)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let item_id = ItemID::new(req.avatar_id);
|
let mut free_select_policy: Option<&FreeSelectItem> = None;
|
||||||
if let None = item_id {
|
let mut free_select_progress: u32 = 0;
|
||||||
return Err(NetError::from(Retcode::RetFail));
|
let mut free_select_required_pull: u32 = 0;
|
||||||
|
for discount_policy_tag in target_pool.discount_policy_tags.iter() {
|
||||||
|
if gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.free_select_map
|
||||||
|
.contains_key(discount_policy_tag)
|
||||||
|
{
|
||||||
|
let policy = gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.free_select_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
let free_select_demand_idx = usize::try_from(
|
||||||
|
*(status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get(&policy.free_select_usage_record_tag)
|
||||||
|
.unwrap()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if policy.milestones.len() <= free_select_demand_idx {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
let item_id = item_id.unwrap();
|
|
||||||
|
|
||||||
let item_type = gacha_model.request_free_agent(target_pool, &item_id);
|
let free_select_actual_progress = status_bin
|
||||||
if item_type == GachaAddedItemType::None {
|
.discount_usage_map
|
||||||
return Err(NetError::from(Retcode::RetFail));
|
.get(&policy.free_select_progress_record_tag)
|
||||||
|
.unwrap();
|
||||||
|
free_select_policy = Some(policy);
|
||||||
|
free_select_required_pull = policy
|
||||||
|
.milestones
|
||||||
|
.get(free_select_demand_idx)
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
free_select_progress = min(free_select_required_pull, *free_select_actual_progress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let _ = add_item(role_model, item_model, &item_id, &item_type);
|
|
||||||
|
|
||||||
_session
|
if let None = free_select_policy {
|
||||||
.notify(construct_sync(role_model, item_model))
|
tracing::info!(
|
||||||
.await?;
|
"refuse free agent because: pool of parent_schedule_id {} hasn't defined free agent discount yet (or used up chance)",
|
||||||
|
req.gacha_parent_schedule_id
|
||||||
|
);
|
||||||
|
return Ok(GachaFreeAgentScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
} else if free_select_progress < free_select_required_pull {
|
||||||
|
tracing::info!(
|
||||||
|
"refuse free agent because: use pulled {free_select_progress} (after last free agent) in parent_schedule_id {}, required {free_select_required_pull}",
|
||||||
|
req.gacha_parent_schedule_id
|
||||||
|
);
|
||||||
|
return Ok(GachaFreeAgentScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let free_select_policy = free_select_policy.unwrap();
|
||||||
|
let mut has_demanded_item = false;
|
||||||
|
for rarity_items in target_pool.gacha_items.iter() {
|
||||||
|
if rarity_items.rarity != free_select_policy.rarity {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (category_tag, category) in rarity_items.categories.iter() {
|
||||||
|
if !free_select_policy.category_tags.contains(category_tag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
has_demanded_item |= category.item_ids.contains(&req.avatar_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !has_demanded_item {
|
||||||
|
tracing::info!(
|
||||||
|
"refuse free agent because: pool of parent_schedule_id {} doesn't have demanded item {}",
|
||||||
|
req.gacha_parent_schedule_id, req.avatar_id
|
||||||
|
);
|
||||||
|
return Ok(GachaFreeAgentScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
role_model.add_avatar(AvatarBaseID::new(req.avatar_id).unwrap());
|
||||||
|
(*status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get_mut(&free_select_policy.free_select_usage_record_tag)
|
||||||
|
.unwrap()) += 1;
|
||||||
|
(*status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get_mut(&free_select_policy.free_select_progress_record_tag)
|
||||||
|
.unwrap()) -= free_select_required_pull;
|
||||||
|
|
||||||
Ok(GachaFreeAgentScRsp {
|
Ok(GachaFreeAgentScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
})
|
})
|
||||||
|
@ -154,82 +291,330 @@ pub async fn on_choose_gacha_up(
|
||||||
&gachaconf.character_gacha_pool_list,
|
&gachaconf.character_gacha_pool_list,
|
||||||
&req.gacha_parent_schedule_id,
|
&req.gacha_parent_schedule_id,
|
||||||
&pull_time,
|
&pull_time,
|
||||||
)?;
|
);
|
||||||
|
if let None = target_pool {
|
||||||
|
return Ok(ChooseGachaUpScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let target_pool = target_pool.unwrap();
|
||||||
|
|
||||||
let item_id = ItemID::new(req.item_id);
|
for rarity_items in target_pool.gacha_items.iter() {
|
||||||
if let None = item_id {
|
if rarity_items.rarity != gachaconf.common_properties.s_item_rarity {
|
||||||
return Err(NetError::from(Retcode::RetFail));
|
continue;
|
||||||
|
}
|
||||||
|
for guarantee_policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
||||||
|
let category_guarantee_policy = gachaconf
|
||||||
|
.category_guarantee_policy_map
|
||||||
|
.get(guarantee_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
if !category_guarantee_policy.chooseable {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut up_category: Option<&String> = None;
|
||||||
|
for (category_tag, category) in rarity_items.categories.iter() {
|
||||||
|
if category.item_ids.contains(&req.item_id) {
|
||||||
|
up_category = Some(category_tag);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let None = up_category {
|
||||||
|
return Ok(ChooseGachaUpScRsp {
|
||||||
|
retcode: Retcode::RetFail.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
let up_category = up_category.unwrap();
|
||||||
|
|
||||||
|
let progress_bin = gacha_model
|
||||||
|
.gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap()
|
||||||
|
.rarity_status_map
|
||||||
|
.get_mut(&rarity_items.rarity)
|
||||||
|
.unwrap();
|
||||||
|
match progress_bin
|
||||||
|
.categories_chosen_guarantee_item_map
|
||||||
|
.entry(guarantee_policy_tag.clone())
|
||||||
|
{
|
||||||
|
Occupied(mut occupied_entry) => {
|
||||||
|
occupied_entry.insert(req.item_id);
|
||||||
|
}
|
||||||
|
Vacant(vacant_entry) => {
|
||||||
|
vacant_entry.insert(req.item_id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match progress_bin
|
||||||
|
.categories_chosen_guarantee_category_map
|
||||||
|
.entry(up_category.clone())
|
||||||
|
{
|
||||||
|
Occupied(mut occupied_entry) => {
|
||||||
|
occupied_entry.insert(up_category.clone());
|
||||||
|
}
|
||||||
|
Vacant(vacant_entry) => {
|
||||||
|
vacant_entry.insert(up_category.clone());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return Ok(ChooseGachaUpScRsp {
|
||||||
|
retcode: Retcode::RetSucc.into(),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let item_id = item_id.unwrap();
|
|
||||||
|
|
||||||
Ok(ChooseGachaUpScRsp {
|
Ok(ChooseGachaUpScRsp {
|
||||||
retcode: if gacha_model.choose_gacha_up(target_pool, &item_id) {
|
retcode: Retcode::RetFail.into(),
|
||||||
Retcode::RetSucc.into()
|
|
||||||
} else {
|
|
||||||
Retcode::RetFail.into()
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn generate_gacha_info_from_pool(
|
||||||
|
gacha_bin: &GachaModelBin,
|
||||||
|
target_pool: &CharacterGachaPool,
|
||||||
|
common_properties: &GachaCommonProperties,
|
||||||
|
) -> Gacha {
|
||||||
|
let gachaconf = data::gacha::global_gacha_config();
|
||||||
|
let sharing_guarantee_category_tag = &target_pool.sharing_guarantee_info_category;
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get(sharing_guarantee_category_tag)
|
||||||
|
.unwrap();
|
||||||
|
let pity_s = status_bin
|
||||||
|
.rarity_status_map
|
||||||
|
.get(&common_properties.s_item_rarity)
|
||||||
|
.unwrap()
|
||||||
|
.pity;
|
||||||
|
let pity_a = status_bin
|
||||||
|
.rarity_status_map
|
||||||
|
.get(&common_properties.a_item_rarity)
|
||||||
|
.unwrap()
|
||||||
|
.pity;
|
||||||
|
|
||||||
|
let mut discount_ten_roll_prize: u32 = 0;
|
||||||
|
let mut discount_avaliable_num: u32 = 0;
|
||||||
|
let mut advanced_s_guarantee: u32 = 0;
|
||||||
|
let mut free_select_progress: u32 = 0;
|
||||||
|
let mut free_select_required_pull: u32 = 0;
|
||||||
|
let mut free_select_policy: Option<&FreeSelectItem> = None;
|
||||||
|
for discount_policy_tag in target_pool.discount_policy_tags.iter() {
|
||||||
|
if common_properties.newcomer_advanced_s_tag == *discount_policy_tag {
|
||||||
|
let policy = gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.advanced_guarantee_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
if status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap()
|
||||||
|
< &policy.use_limit
|
||||||
|
{
|
||||||
|
advanced_s_guarantee = policy.guarantee_pity - pity_s + 1;
|
||||||
|
}
|
||||||
|
} else if common_properties.ten_pull_discount_tag == *discount_policy_tag {
|
||||||
|
let policy = gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.ten_pull_discount_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
let discount_usage = status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
if discount_usage < &policy.use_limit {
|
||||||
|
discount_ten_roll_prize = policy.discounted_prize;
|
||||||
|
discount_avaliable_num = policy.use_limit - discount_usage;
|
||||||
|
}
|
||||||
|
} else if gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.free_select_map
|
||||||
|
.contains_key(discount_policy_tag)
|
||||||
|
{
|
||||||
|
let policy = gachaconf
|
||||||
|
.discount_policies
|
||||||
|
.free_select_map
|
||||||
|
.get(discount_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
let free_select_demand_idx = usize::try_from(
|
||||||
|
*(status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get(&policy.free_select_usage_record_tag)
|
||||||
|
.unwrap()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if policy.milestones.len() <= free_select_demand_idx {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let free_select_actual_progress = status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get(&policy.free_select_progress_record_tag)
|
||||||
|
.unwrap();
|
||||||
|
free_select_policy = Some(policy);
|
||||||
|
free_select_required_pull = policy
|
||||||
|
.milestones
|
||||||
|
.get(free_select_demand_idx)
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
free_select_progress = min(free_select_required_pull, *free_select_actual_progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut up_s_item_list: Vec<u32> = vec![];
|
||||||
|
let mut up_a_item_list: Vec<u32> = vec![];
|
||||||
|
let mut free_select_item_list: Vec<u32> = vec![];
|
||||||
|
let mut chooseable_up_list: Vec<u32> = vec![];
|
||||||
|
let mut chosen_up_item: u32 = 0;
|
||||||
|
let mut s_guarantee: u32 = 0;
|
||||||
|
let mut a_guarantee: u32 = 0;
|
||||||
|
for rarity_items in target_pool.gacha_items.iter() {
|
||||||
|
let mut chooseable_up_included_category_tags: Option<&HashSet<String>> = None;
|
||||||
|
let mut chooseable_policy_tag: Option<&String> = None;
|
||||||
|
for guarantee_policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
||||||
|
let category_guarantee_policy = gachaconf
|
||||||
|
.category_guarantee_policy_map
|
||||||
|
.get(guarantee_policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
if !category_guarantee_policy.chooseable {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
chooseable_policy_tag = Some(guarantee_policy_tag);
|
||||||
|
chooseable_up_included_category_tags =
|
||||||
|
Some(&category_guarantee_policy.included_category_tags);
|
||||||
|
if let Some(item) = status_bin
|
||||||
|
.rarity_status_map
|
||||||
|
.get(&rarity_items.rarity)
|
||||||
|
.unwrap()
|
||||||
|
.categories_chosen_guarantee_item_map
|
||||||
|
.get(guarantee_policy_tag)
|
||||||
|
{
|
||||||
|
chosen_up_item = item.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (category_tag, category) in rarity_items.categories.iter() {
|
||||||
|
let probability_model = gachaconf
|
||||||
|
.probability_model_map
|
||||||
|
.get(&rarity_items.probability_model_tag)
|
||||||
|
.unwrap();
|
||||||
|
let maximum_pity = &probability_model.maximum_guarantee_pity;
|
||||||
|
if rarity_items.rarity == common_properties.s_item_rarity {
|
||||||
|
if category.is_promotional_items {
|
||||||
|
up_s_item_list = category.item_ids.clone();
|
||||||
|
}
|
||||||
|
// tracing::info!("pity_s: {pity_s}");
|
||||||
|
// thread 'tokio-runtime-worker' panicked at nap_gameserver\src\handlers\gacha.rs:369:31:
|
||||||
|
// attempt to subtract with overflow
|
||||||
|
s_guarantee = maximum_pity - min(pity_s, maximum_pity.clone()) + 1;
|
||||||
|
}
|
||||||
|
if rarity_items.rarity == common_properties.a_item_rarity {
|
||||||
|
if category.is_promotional_items {
|
||||||
|
up_a_item_list = category.item_ids.clone();
|
||||||
|
}
|
||||||
|
// tracing::info!("pity_a: {pity_a}");
|
||||||
|
a_guarantee = maximum_pity - min(pity_a, maximum_pity.clone()) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(val) = free_select_policy {
|
||||||
|
if val.rarity == rarity_items.rarity && val.category_tags.contains(category_tag) {
|
||||||
|
free_select_item_list.append(&mut category.item_ids.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(tags) = chooseable_up_included_category_tags {
|
||||||
|
if tags.contains(category_tag) {
|
||||||
|
chooseable_up_list.append(&mut category.item_ids.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(priority_policy_tag) = chooseable_policy_tag {
|
||||||
|
// if let Some(item) = status_bin
|
||||||
|
// .rarity_status_map
|
||||||
|
// .get(&rarity_items.rarity)
|
||||||
|
// .unwrap()
|
||||||
|
// .categories_chosen_guarantee_item_map
|
||||||
|
// .get(priority_policy_tag)
|
||||||
|
// {
|
||||||
|
if rarity_items.rarity == gachaconf.common_properties.s_item_rarity {
|
||||||
|
up_s_item_list = vec![];
|
||||||
|
} else if rarity_items.rarity == gachaconf.common_properties.a_item_rarity {
|
||||||
|
up_a_item_list = vec![];
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let need_item_info_list: Vec<NeedItemInfo> = vec![NeedItemInfo {
|
||||||
|
need_item_id: target_pool.cost_item_id,
|
||||||
|
need_item_count: 1,
|
||||||
|
}];
|
||||||
|
|
||||||
|
let mut result = Gacha {
|
||||||
|
gacha_schedule_id: target_pool.gacha_schedule_id,
|
||||||
|
gacha_parent_schedule_id: target_pool.gacha_parent_schedule_id,
|
||||||
|
gacha_type: target_pool.gacha_type,
|
||||||
|
start_timestamp: target_pool.start_time.timestamp(),
|
||||||
|
end_timestamp: target_pool.end_time.timestamp(),
|
||||||
|
discount_avaliable_num,
|
||||||
|
discount_ten_roll_prize,
|
||||||
|
advanced_s_guarantee,
|
||||||
|
s_guarantee,
|
||||||
|
a_guarantee,
|
||||||
|
need_item_info_list,
|
||||||
|
free_select_progress,
|
||||||
|
free_select_required_pull,
|
||||||
|
free_select_item_list,
|
||||||
|
chosen_up_item,
|
||||||
|
// nammdglepbk: 563,
|
||||||
|
// hgmcofcjmbg: 101,
|
||||||
|
// akggbhgkifd: chooseable_up_list.clone(),
|
||||||
|
chooseable_up_list,
|
||||||
|
..Gacha::default()
|
||||||
|
};
|
||||||
|
if up_s_item_list.len() > 0 {
|
||||||
|
result.up_s_item_list = up_s_item_list;
|
||||||
|
}
|
||||||
|
if up_a_item_list.len() > 0 {
|
||||||
|
result.up_a_item_list = up_a_item_list;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_all_gacha_info(_player: &Player, now: &DateTime<Local>) -> GachaData {
|
||||||
|
let gachaconf = global_gacha_config();
|
||||||
|
let gacha_bin = &_player.gacha_model.gacha_bin;
|
||||||
|
let mut gacha_list: Vec<Gacha> = vec![];
|
||||||
|
for target_pool in gachaconf.character_gacha_pool_list.iter() {
|
||||||
|
if target_pool.is_still_open(now) {
|
||||||
|
gacha_list.push(generate_gacha_info_from_pool(
|
||||||
|
&gacha_bin,
|
||||||
|
target_pool,
|
||||||
|
&gachaconf.common_properties,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracing::info!("gacha_list: {:?}", gacha_list);
|
||||||
|
GachaData {
|
||||||
|
random_number: 6167,
|
||||||
|
gacha_pool: Some(GachaPool { gacha_list }),
|
||||||
|
..GachaData::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_gacha_pool<'conf>(
|
fn get_gacha_pool<'conf>(
|
||||||
character_gacha_pool_list: &'conf Vec<CharacterGachaPool>,
|
character_gacha_pool_list: &'conf Vec<CharacterGachaPool>,
|
||||||
gacha_parent_schedule_id: &u32,
|
gacha_parent_schedule_id: &u32,
|
||||||
pull_time: &DateTime<Local>,
|
pull_time: &DateTime<Local>,
|
||||||
) -> NetResult<&'conf CharacterGachaPool> {
|
) -> Option<&'conf CharacterGachaPool> {
|
||||||
for target_pool in character_gacha_pool_list.iter() {
|
for target_pool in character_gacha_pool_list.iter() {
|
||||||
if &target_pool.gacha_parent_schedule_id == gacha_parent_schedule_id
|
if &target_pool.gacha_parent_schedule_id == gacha_parent_schedule_id
|
||||||
&& target_pool.is_still_open(pull_time)
|
&& target_pool.is_still_open(pull_time)
|
||||||
{
|
{
|
||||||
return Ok(target_pool);
|
return Some(target_pool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracing::info!(
|
None
|
||||||
"refuse gacha op because: pool of parent_schedule_id {} not found or isn't in open time",
|
|
||||||
gacha_parent_schedule_id
|
|
||||||
);
|
|
||||||
Err(NetError::from(Retcode::RetFail))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return is item UID (weapon specific)
|
|
||||||
fn add_item(
|
|
||||||
role_model: &mut RoleModel,
|
|
||||||
item_model: &mut ItemModel,
|
|
||||||
item_id: &ItemID,
|
|
||||||
item_type: &GachaAddedItemType,
|
|
||||||
) -> NetResult<u32> {
|
|
||||||
match item_type {
|
|
||||||
GachaAddedItemType::Character => match AvatarBaseID::new(item_id.value()) {
|
|
||||||
Some(avatar_id) => {
|
|
||||||
role_model.add_avatar(avatar_id);
|
|
||||||
Ok(0)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
tracing::info!("add item failed for avatar id {item_id}");
|
|
||||||
Err(NetError::from(Retcode::RetFail))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
GachaAddedItemType::Weapon => match WeaponID::new(item_id.value()) {
|
|
||||||
Some(weapon_id) => Ok(item_model.add_weapon(weapon_id).value()),
|
|
||||||
None => {
|
|
||||||
tracing::info!("add item failed for weapon id {item_id}");
|
|
||||||
Err(NetError::from(Retcode::RetFail))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
GachaAddedItemType::Bangboo => Ok(0),
|
|
||||||
_ => {
|
|
||||||
tracing::info!(
|
|
||||||
"add item failed due to undefined item type (from {item_id}) in configuration"
|
|
||||||
);
|
|
||||||
Err(NetError::from(Retcode::RetFail))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct_sync(role_model: &RoleModel, item_model: &ItemModel) -> PlayerSyncScNotify {
|
|
||||||
PlayerSyncScNotify {
|
|
||||||
avatar: Some(role_model.avatar_sync()),
|
|
||||||
item_sync: Some(item_model.item_sync()),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,10 +98,7 @@ req_handlers! {
|
||||||
world::LeaveCurDungeon;
|
world::LeaveCurDungeon;
|
||||||
world::InteractWithUnit;
|
world::InteractWithUnit;
|
||||||
world::EnterSection;
|
world::EnterSection;
|
||||||
world::JumpPageSystem;
|
world::ArchiveQuestsSeen;
|
||||||
world::StartHollowQuest;
|
|
||||||
world::FinishHollowBattleEvent;
|
|
||||||
world::LongFightProgressUpdate;
|
|
||||||
client_systems::ReportUiLayoutPlatform;
|
client_systems::ReportUiLayoutPlatform;
|
||||||
client_systems::PlayerOperation;
|
client_systems::PlayerOperation;
|
||||||
client_systems::UnlockNewbieGroup;
|
client_systems::UnlockNewbieGroup;
|
||||||
|
@ -110,7 +107,6 @@ req_handlers! {
|
||||||
client_systems::ReportSystemSettingsChange;
|
client_systems::ReportSystemSettingsChange;
|
||||||
client_systems::InteractWithSceneObject;
|
client_systems::InteractWithSceneObject;
|
||||||
client_systems::PlayerSystemParameterChange;
|
client_systems::PlayerSystemParameterChange;
|
||||||
client_systems::NewsStandSeen;
|
|
||||||
perform::PerformTrigger;
|
perform::PerformTrigger;
|
||||||
perform::PerformEnd;
|
perform::PerformEnd;
|
||||||
perform::PerformJump;
|
perform::PerformJump;
|
||||||
|
@ -126,9 +122,6 @@ req_handlers! {
|
||||||
gacha::DoGacha;
|
gacha::DoGacha;
|
||||||
gacha::ChooseGachaUp;
|
gacha::ChooseGachaUp;
|
||||||
gacha::GachaFreeAgent;
|
gacha::GachaFreeAgent;
|
||||||
player::ModNickname;
|
|
||||||
client_systems::ModQuickMenu;
|
|
||||||
client_systems::ChangePostGirl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_handlers! {
|
notify_handlers! {
|
||||||
|
|
|
@ -58,25 +58,6 @@ pub async fn on_get_player_transaction(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_mod_nickname(
|
|
||||||
session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: ModNicknameCsReq,
|
|
||||||
) -> NetResult<ModNicknameScRsp> {
|
|
||||||
_player.basic_data_model.nick_name = Some(_req.nick_name.to_string());
|
|
||||||
session
|
|
||||||
.notify(PlayerSyncScNotify {
|
|
||||||
basic_info: Some(_player.basic_data_model.player_basic_info()),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(ModNicknameScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn on_keep_alive(
|
pub async fn on_keep_alive(
|
||||||
_session: &NetSession,
|
_session: &NetSession,
|
||||||
_player: &mut Player,
|
_player: &mut Player,
|
||||||
|
|
|
@ -16,22 +16,13 @@ pub async fn on_get_quest_data(
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
quest_type: req.quest_type,
|
quest_type: req.quest_type,
|
||||||
quest_data: Some(QuestData {
|
quest_data: Some(QuestData {
|
||||||
quest_collection_list: vec![
|
quest_collection_list: vec![QuestCollection {
|
||||||
QuestCollection {
|
|
||||||
quest_type: EQuestType::ArchiveFile as u32,
|
quest_type: EQuestType::ArchiveFile as u32,
|
||||||
quest_id_list: tables::archive_file_quest_template_tb::iter()
|
quest_id_list: tables::archive_file_quest_template_tb::iter()
|
||||||
.map(|tmpl| tmpl.id.value())
|
.map(|tmpl| tmpl.id.value())
|
||||||
.collect(),
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
}],
|
||||||
QuestCollection {
|
|
||||||
quest_type: EQuestType::Hollow as u32,
|
|
||||||
quest_id_list: tables::hollow_quest_template_tb::iter()
|
|
||||||
.map(|tmpl| tmpl.id.value())
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -44,19 +35,22 @@ pub async fn on_get_yorozuya_info(
|
||||||
Ok(GetYorozuyaInfoScRsp {
|
Ok(GetYorozuyaInfoScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
yorozuya_info: Some(YorozuyaInfo {
|
yorozuya_info: Some(YorozuyaInfo {
|
||||||
odohdljfdlf: vec![1000, 1001, 1002, 1003, 1004],
|
odohdljfdlf: vec![1001],
|
||||||
apmojjlcooa: vec![1000, 1001, 1002, 1003, 1004],
|
apmojjlcooa: vec![1001],
|
||||||
akiddbalfoa: vec![10010001, 10010002, 10010004],
|
npgjhahijkb: vec![100001, 100101, 100401, 109901],
|
||||||
npgjhahijkb: tables::hollow_config_template_tb::iter()
|
eoljpdnjgeg: vec![
|
||||||
.map(|tmpl| tmpl.id.value())
|
Ofhlkjeakif {
|
||||||
.collect(),
|
nnkcanmllod: 199030,
|
||||||
eoljpdnjgeg: tables::hollow_quest_template_tb::iter()
|
|
||||||
.map(|tmpl| Ofhlkjeakif {
|
|
||||||
nnkcanmllod: tmpl.id.value(),
|
|
||||||
kkjlnkehddj: Some(Cgpajijemlj::default()),
|
kkjlnkehddj: Some(Cgpajijemlj::default()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
},
|
||||||
.collect(),
|
Ofhlkjeakif {
|
||||||
|
nnkcanmllod: 199035,
|
||||||
|
ggnbpiofdpp: 110103,
|
||||||
|
kkjlnkehddj: Some(Cgpajijemlj::default()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,12 @@
|
||||||
use data::{
|
use data::{
|
||||||
event,
|
event,
|
||||||
tables::{HollowQuestID, ProcedureConfigID, SectionConfigID, TrainingQuestID},
|
tables::{ProcedureConfigID, SectionConfigID, TrainingQuestID},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::core::NetError;
|
use super::core::NetError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
logic::{
|
logic::{game::*, procedure::ProcedureAction, ELocalPlayType, ENPCInteraction},
|
||||||
game::*, procedure::ProcedureAction, EHollowQuestType, ELocalPlayType, ENPCInteraction,
|
|
||||||
},
|
|
||||||
net::NetSessionState,
|
net::NetSessionState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -184,42 +182,10 @@ pub async fn on_start_trial_fighting_mission(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_end_battle(
|
pub async fn on_end_battle(
|
||||||
session: &NetSession,
|
_session: &NetSession,
|
||||||
player: &mut Player,
|
_player: &mut Player,
|
||||||
req: EndBattleCsReq,
|
_req: EndBattleCsReq,
|
||||||
) -> NetResult<EndBattleScRsp> {
|
) -> NetResult<EndBattleScRsp> {
|
||||||
match &mut player.game_instance {
|
|
||||||
GameInstance::Hollow(hollow) if hollow.quest_manager.has_active_quests() => {
|
|
||||||
hollow
|
|
||||||
.quest_manager
|
|
||||||
.finish_quest(hollow.battle_event_id.value())
|
|
||||||
.map_err(LogicError::from)?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.notify(DungeonQuestFinishedScNotify {
|
|
||||||
result: req.battle_result.unwrap().result as u32,
|
|
||||||
quest_id: hollow.quest_id,
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
GameInstance::LongFight(fight) => {
|
|
||||||
fight
|
|
||||||
.quest_manager
|
|
||||||
.finish_quest(fight.battle_event_id.value())
|
|
||||||
.map_err(LogicError::from)?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.notify(DungeonQuestFinishedScNotify {
|
|
||||||
result: req.battle_result.unwrap().result as u32,
|
|
||||||
quest_id: fight.quest_id,
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(EndBattleScRsp {
|
Ok(EndBattleScRsp {
|
||||||
battle_reward: Some(BattleRewardInfo::default()),
|
battle_reward: Some(BattleRewardInfo::default()),
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
|
@ -293,79 +259,13 @@ pub async fn on_enter_section(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_jump_page_system(
|
pub async fn on_archive_quests_seen(
|
||||||
_session: &NetSession,
|
_session: &NetSession,
|
||||||
_player: &mut Player,
|
_player: &mut Player,
|
||||||
_req: JumpPageSystemCsReq,
|
_req: ArchiveQuestsSeenCsReq,
|
||||||
) -> NetResult<JumpPageSystemScRsp> {
|
) -> NetResult<ArchiveQuestsSeenScRsp> {
|
||||||
Ok(JumpPageSystemScRsp {
|
Ok(ArchiveQuestsSeenScRsp {
|
||||||
retcode: Retcode::RetSucc.into(),
|
retcode: Retcode::RetSucc.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_start_hollow_quest(
|
|
||||||
session: &NetSession,
|
|
||||||
player: &mut Player,
|
|
||||||
req: StartHollowQuestCsReq,
|
|
||||||
) -> NetResult<StartHollowQuestScRsp> {
|
|
||||||
use crate::logic::{TimePeriodType, WeatherType};
|
|
||||||
|
|
||||||
let quest_id = HollowQuestID::new(req.quest_id).ok_or(Retcode::RetFail)?;
|
|
||||||
let quest_type = EHollowQuestType::from(quest_id.template().hollow_quest_type);
|
|
||||||
|
|
||||||
match quest_type {
|
|
||||||
EHollowQuestType::RallyBattle => {
|
|
||||||
player.game_instance = GameInstance::LongFight(
|
|
||||||
LongFightGame::create_rally_game(
|
|
||||||
quest_id,
|
|
||||||
&req.avatars,
|
|
||||||
req.buddy_id,
|
|
||||||
TimePeriodType::from_str(&req.quest_time_period),
|
|
||||||
WeatherType::from_str(&req.quest_weather),
|
|
||||||
)
|
|
||||||
.map_err(LogicError::from)?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
player.game_instance = GameInstance::Hollow(
|
|
||||||
HollowGame::create_pure_hollow_battle(
|
|
||||||
quest_id,
|
|
||||||
&req.avatars,
|
|
||||||
req.buddy_id,
|
|
||||||
TimePeriodType::from_str(&req.quest_time_period),
|
|
||||||
WeatherType::from_str(&req.quest_weather),
|
|
||||||
)
|
|
||||||
.map_err(LogicError::from)?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let world_init_notify = player.game_instance.create_world_init_notify()?;
|
|
||||||
session.notify(world_init_notify).await?;
|
|
||||||
|
|
||||||
Ok(StartHollowQuestScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
quest_id: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn on_finish_hollow_battle_event(
|
|
||||||
_session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: FinishHollowBattleEventCsReq,
|
|
||||||
) -> NetResult<FinishHollowBattleEventScRsp> {
|
|
||||||
Ok(FinishHollowBattleEventScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn on_long_fight_progress_update(
|
|
||||||
_session: &NetSession,
|
|
||||||
_player: &mut Player,
|
|
||||||
_req: LongFightProgressUpdateCsReq,
|
|
||||||
) -> NetResult<LongFightProgressUpdateScRsp> {
|
|
||||||
Ok(LongFightProgressUpdateScRsp {
|
|
||||||
retcode: Retcode::RetSucc.into(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::logic::BaseProperty;
|
use crate::logic::BaseProperty;
|
||||||
use proto::AvatarUnitInfo;
|
use proto::InLevelAvatarData;
|
||||||
|
|
||||||
pub struct AvatarUnit {
|
pub struct InLevelAvatarDataItem {
|
||||||
pub avatar_id: u32,
|
pub avatar_id: u32,
|
||||||
pub mp_property_override: HashMap<BaseProperty, i32>,
|
pub mp_property_override: HashMap<BaseProperty, i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AvatarUnit {
|
impl InLevelAvatarDataItem {
|
||||||
pub fn to_client(&self) -> AvatarUnitInfo {
|
pub fn to_client(&self) -> InLevelAvatarData {
|
||||||
AvatarUnitInfo {
|
InLevelAvatarData {
|
||||||
avatar_id: self.avatar_id,
|
avatar_id: self.avatar_id,
|
||||||
mp_property_override_map: self
|
mp_property_override_map: self
|
||||||
.mp_property_override
|
.mp_property_override
|
|
@ -1,18 +1,18 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use proto::BuddyUnitInfo;
|
use proto::EquippedBuddyData;
|
||||||
|
|
||||||
use crate::logic::{BaseProperty, BuddyTeamType};
|
use crate::logic::{BaseProperty, BuddyTeamType};
|
||||||
|
|
||||||
pub struct BuddyUnit {
|
pub struct EquippedBuddyDataItem {
|
||||||
pub buddy_id: u32,
|
pub buddy_id: u32,
|
||||||
pub buddy_team: BuddyTeamType,
|
pub buddy_team: BuddyTeamType,
|
||||||
pub override_property_map: HashMap<BaseProperty, i32>,
|
pub override_property_map: HashMap<BaseProperty, i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BuddyUnit {
|
impl EquippedBuddyDataItem {
|
||||||
pub fn to_client(&self) -> BuddyUnitInfo {
|
pub fn to_client(&self) -> EquippedBuddyData {
|
||||||
BuddyUnitInfo {
|
EquippedBuddyData {
|
||||||
buddy_id: self.buddy_id,
|
buddy_id: self.buddy_id,
|
||||||
r#type: self.buddy_team.to_protocol().into(),
|
r#type: self.buddy_team.to_protocol().into(),
|
||||||
mp_property_override_map: self
|
mp_property_override_map: self
|
|
@ -1,67 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use data::tables::{BattleEventConfigID, OnceRewardID};
|
|
||||||
use proto::{FightDropInfo, FightReward, RewardItems};
|
|
||||||
|
|
||||||
pub struct FightDropPool {
|
|
||||||
special_drop: Vec<SpecialReward>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SpecialReward {
|
|
||||||
pub reward_id: OnceRewardID,
|
|
||||||
pub item_count_map: HashMap<u32, u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FightDropPool {
|
|
||||||
pub fn new(battle_event_id: BattleEventConfigID) -> Self {
|
|
||||||
let template = battle_event_id.template();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
special_drop: template
|
|
||||||
.special_drop
|
|
||||||
.iter()
|
|
||||||
.map(|id| SpecialReward::new(*id))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> FightDropInfo {
|
|
||||||
FightDropInfo {
|
|
||||||
normal_drop_list: Vec::new(),
|
|
||||||
special_drop_list: self
|
|
||||||
.special_drop
|
|
||||||
.iter()
|
|
||||||
.map(SpecialReward::to_client)
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpecialReward {
|
|
||||||
pub fn new(template_id: OnceRewardID) -> Self {
|
|
||||||
let template = template_id.template();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
reward_id: template_id,
|
|
||||||
item_count_map: template
|
|
||||||
.reward_list
|
|
||||||
.iter()
|
|
||||||
.map(|r| (r.reward_item_id, r.reward_amount))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> FightReward {
|
|
||||||
FightReward {
|
|
||||||
reward_id: self.reward_id.value(),
|
|
||||||
fight_reward_map: HashMap::from([(
|
|
||||||
0,
|
|
||||||
RewardItems {
|
|
||||||
reward_item_map: self.item_count_map.clone(),
|
|
||||||
},
|
|
||||||
)]),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
mod fight_drop;
|
|
||||||
pub use fight_drop::FightDropPool;
|
|
|
@ -1,9 +1,7 @@
|
||||||
pub mod drop;
|
mod avatar;
|
||||||
mod quest;
|
mod buddy;
|
||||||
mod team;
|
mod team;
|
||||||
pub mod unit;
|
|
||||||
mod variable;
|
|
||||||
|
|
||||||
pub use quest::{DungeonQuestError, DungeonQuestManager};
|
pub use avatar::InLevelAvatarDataItem;
|
||||||
pub use team::{BuddyParam, TeamDataItem};
|
pub use buddy::EquippedBuddyDataItem;
|
||||||
pub use variable::LogicVariableTable;
|
pub use team::TeamDataItem;
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
use data::tables::BattleGroupConfigID;
|
|
||||||
use proto::DungeonQuestInfo;
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct DungeonQuestManager {
|
|
||||||
inner_quests: Vec<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum DungeonQuestError {
|
|
||||||
#[error("dungeon inner quest with id {0} is not active")]
|
|
||||||
QuestNotActive(u32),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DungeonQuestManager {
|
|
||||||
pub fn new_for_battle_group(battle_group_id: BattleGroupConfigID) -> Self {
|
|
||||||
Self {
|
|
||||||
inner_quests: vec![battle_group_id.template().battle_event_id.value()],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn finish_quest(&mut self, quest_id: u32) -> Result<(), DungeonQuestError> {
|
|
||||||
let idx = self
|
|
||||||
.inner_quests
|
|
||||||
.iter()
|
|
||||||
.position(|id| *id == quest_id)
|
|
||||||
.ok_or(DungeonQuestError::QuestNotActive(quest_id))?;
|
|
||||||
|
|
||||||
self.inner_quests.remove(idx);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_active_quests(&self) -> bool {
|
|
||||||
!self.inner_quests.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> DungeonQuestInfo {
|
|
||||||
DungeonQuestInfo {
|
|
||||||
inner_quest_id_list: self.inner_quests.clone(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,33 +2,30 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::logic::BuddyTeamType;
|
use crate::logic::BuddyTeamType;
|
||||||
|
|
||||||
use super::unit::{AvatarUnit, BuddyUnit};
|
use super::{EquippedBuddyDataItem, InLevelAvatarDataItem};
|
||||||
|
|
||||||
pub struct TeamDataItem {
|
pub struct TeamDataItem {
|
||||||
pub avatar_member_list: Vec<AvatarUnit>,
|
pub avatar_member_list: Vec<InLevelAvatarDataItem>,
|
||||||
pub equipped_buddy_list: Vec<BuddyUnit>,
|
pub equipped_buddy_list: Vec<EquippedBuddyDataItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BuddyParam(pub u32, pub BuddyTeamType);
|
|
||||||
|
|
||||||
impl TeamDataItem {
|
impl TeamDataItem {
|
||||||
pub fn new(avatars: &[u32], buddy_params: &[BuddyParam]) -> Self {
|
pub fn new(avatars: &[u32], buddy_id: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
avatar_member_list: avatars
|
avatar_member_list: avatars
|
||||||
.iter()
|
.iter()
|
||||||
.map(|id| AvatarUnit {
|
.map(|id| InLevelAvatarDataItem {
|
||||||
avatar_id: *id,
|
avatar_id: *id,
|
||||||
mp_property_override: HashMap::new(),
|
mp_property_override: HashMap::new(),
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
equipped_buddy_list: buddy_params
|
equipped_buddy_list: (buddy_id != 0)
|
||||||
.iter()
|
.then_some(vec![EquippedBuddyDataItem {
|
||||||
.map(|param| BuddyUnit {
|
buddy_id,
|
||||||
buddy_id: param.0,
|
buddy_team: BuddyTeamType::Assisting,
|
||||||
buddy_team: param.1,
|
|
||||||
override_property_map: HashMap::new(),
|
override_property_map: HashMap::new(),
|
||||||
})
|
}])
|
||||||
.collect(),
|
.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
mod avatar;
|
|
||||||
mod buddy;
|
|
||||||
|
|
||||||
pub use avatar::AvatarUnit;
|
|
||||||
pub use buddy::BuddyUnit;
|
|
|
@ -1,74 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use data::tables::{self, BattleEventConfigID, VariableDataID, VariableValueType};
|
|
||||||
use proto::FightVariable;
|
|
||||||
|
|
||||||
pub struct LogicVariableTable {
|
|
||||||
variable_map: HashMap<String, LogicVariable>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LogicVariableTable {
|
|
||||||
pub fn new(battle_event_id: BattleEventConfigID) -> Self {
|
|
||||||
let event_id = battle_event_id.value();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
variable_map: tables::variable_data_template_tb::iter()
|
|
||||||
.filter(|tmpl| tmpl.battle_event_id == event_id)
|
|
||||||
.map(|tmpl| (tmpl.variable_name.clone(), LogicVariable::new(tmpl.id)))
|
|
||||||
.collect(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> HashMap<String, FightVariable> {
|
|
||||||
self.variable_map
|
|
||||||
.iter()
|
|
||||||
.map(|(name, var)| (name.clone(), var.to_client()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum LogicVariable {
|
|
||||||
Int(i64),
|
|
||||||
Float(f64),
|
|
||||||
Bool(bool),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LogicVariable {
|
|
||||||
pub fn new(id: VariableDataID) -> Self {
|
|
||||||
let template = id.template();
|
|
||||||
|
|
||||||
match template.value_type {
|
|
||||||
VariableValueType::Int => Self::Int(template.initial_value.parse().unwrap_or_default()),
|
|
||||||
VariableValueType::Bool => Self::Bool(
|
|
||||||
template
|
|
||||||
.initial_value
|
|
||||||
.to_lowercase()
|
|
||||||
.parse()
|
|
||||||
.unwrap_or_default(),
|
|
||||||
),
|
|
||||||
VariableValueType::Float => {
|
|
||||||
Self::Float(template.initial_value.parse().unwrap_or_default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> FightVariable {
|
|
||||||
match self {
|
|
||||||
Self::Int(val) => FightVariable {
|
|
||||||
r#type: 1,
|
|
||||||
int_value: *val,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Self::Bool(val) => FightVariable {
|
|
||||||
r#type: 4,
|
|
||||||
int_value: *val as i64,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Self::Float(val) => FightVariable {
|
|
||||||
r#type: 2,
|
|
||||||
float_value: *val,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,7 +12,6 @@ pub enum ESceneType {
|
||||||
Fight = 3,
|
Fight = 3,
|
||||||
Fresh = 4,
|
Fresh = 4,
|
||||||
MultiFight = 5,
|
MultiFight = 5,
|
||||||
LongFight = 7,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -27,28 +26,6 @@ pub enum EQuestType {
|
||||||
HollowChallenge = 6,
|
HollowChallenge = 6,
|
||||||
ArchiveBattle = 7,
|
ArchiveBattle = 7,
|
||||||
Knowledge = 8,
|
Knowledge = 8,
|
||||||
Daily = 9,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive)]
|
|
||||||
#[repr(u32)]
|
|
||||||
pub enum EHollowQuestType {
|
|
||||||
ChallengeChaos = 6,
|
|
||||||
BossRushBattle = 14,
|
|
||||||
World = 8,
|
|
||||||
MainQuest = 1,
|
|
||||||
SideQuest = 2,
|
|
||||||
#[default]
|
|
||||||
Common = 0,
|
|
||||||
Challenge = 5,
|
|
||||||
PromoteBattle = 11,
|
|
||||||
DifficutyBattle = 12,
|
|
||||||
AvatarSide = 7,
|
|
||||||
RallyBattle = 13,
|
|
||||||
Urgent = 3,
|
|
||||||
UrgentSupplement = 4,
|
|
||||||
NormalBattle = 10,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, FromPrimitive)]
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy, FromPrimitive)]
|
||||||
|
@ -125,17 +102,6 @@ pub enum TimePeriodType {
|
||||||
Night = 2,
|
Night = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimePeriodType {
|
|
||||||
pub fn from_str(s: &str) -> Self {
|
|
||||||
match s {
|
|
||||||
"Morning" => Self::Morning,
|
|
||||||
"Evening" => Self::Evening,
|
|
||||||
"Night" => Self::Night,
|
|
||||||
_ => Self::Morning,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for TimePeriodType {
|
impl Display for TimePeriodType {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Debug::fmt(self, f)
|
std::fmt::Debug::fmt(self, f)
|
||||||
|
@ -156,21 +122,6 @@ pub enum WeatherType {
|
||||||
None = 0xFFFFFFFF,
|
None = 0xFFFFFFFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WeatherType {
|
|
||||||
pub fn from_str(s: &str) -> Self {
|
|
||||||
match s {
|
|
||||||
"SunShine" => Self::SunShine,
|
|
||||||
"Fog" => Self::Fog,
|
|
||||||
"Cloudy" => Self::Cloudy,
|
|
||||||
"Rain" => Self::Rain,
|
|
||||||
"Thunder" => Self::Thunder,
|
|
||||||
"ThickFog" => Self::ThickFog,
|
|
||||||
"ThickCloudy" => Self::ThickCloudy,
|
|
||||||
_ => Self::SunShine,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for WeatherType {
|
impl Display for WeatherType {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
std::fmt::Debug::fmt(self, f)
|
std::fmt::Debug::fmt(self, f)
|
||||||
|
@ -313,7 +264,7 @@ pub enum BaseProperty {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
pub enum BuddyTeamType {
|
pub enum BuddyTeamType {
|
||||||
RallyGuidance = 0,
|
Unknown = 0,
|
||||||
Fighting = 1,
|
Fighting = 1,
|
||||||
Assisting = 2,
|
Assisting = 2,
|
||||||
}
|
}
|
||||||
|
@ -321,7 +272,7 @@ pub enum BuddyTeamType {
|
||||||
impl BuddyTeamType {
|
impl BuddyTeamType {
|
||||||
pub fn to_protocol(&self) -> ::proto::BuddyTeamType {
|
pub fn to_protocol(&self) -> ::proto::BuddyTeamType {
|
||||||
match *self {
|
match *self {
|
||||||
Self::RallyGuidance => ::proto::BuddyTeamType::RallyGuidance,
|
Self::Unknown => ::proto::BuddyTeamType::Unknown,
|
||||||
Self::Fighting => ::proto::BuddyTeamType::Fighting,
|
Self::Fighting => ::proto::BuddyTeamType::Fighting,
|
||||||
Self::Assisting => ::proto::BuddyTeamType::Assisting,
|
Self::Assisting => ::proto::BuddyTeamType::Assisting,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,440 +0,0 @@
|
||||||
use data::gacha::gacha_config::*;
|
|
||||||
use data::gacha::global_gacha_config;
|
|
||||||
use data::tables::ItemID;
|
|
||||||
|
|
||||||
use chrono::{DateTime, Local};
|
|
||||||
use proto::{Gacha, GachaData, GachaPool, NeedItemInfo};
|
|
||||||
use std::{
|
|
||||||
cmp::min,
|
|
||||||
collections::{
|
|
||||||
hash_map::Entry::{Occupied, Vacant},
|
|
||||||
HashSet,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::GachaModel;
|
|
||||||
|
|
||||||
impl GachaModel {
|
|
||||||
pub fn to_client(&self, now: &DateTime<Local>) -> GachaData {
|
|
||||||
let gachaconf = global_gacha_config();
|
|
||||||
let mut gacha_list: Vec<Gacha> = vec![];
|
|
||||||
for target_pool in gachaconf.character_gacha_pool_list.iter() {
|
|
||||||
if target_pool.is_still_open(now) {
|
|
||||||
gacha_list.push(
|
|
||||||
self.generate_gacha_info_from_pool(target_pool, &gachaconf.common_properties),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// tracing::info!("gacha_list: {:?}", gacha_list);
|
|
||||||
GachaData {
|
|
||||||
random_number: 6167,
|
|
||||||
gacha_pool: Some(GachaPool { gacha_list }),
|
|
||||||
..GachaData::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_gacha_info_from_pool(
|
|
||||||
&self,
|
|
||||||
target_pool: &CharacterGachaPool,
|
|
||||||
common_properties: &GachaCommonProperties,
|
|
||||||
) -> Gacha {
|
|
||||||
let gachaconf = data::gacha::global_gacha_config();
|
|
||||||
let sharing_guarantee_category_tag = &target_pool.sharing_guarantee_info_category;
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get(sharing_guarantee_category_tag)
|
|
||||||
.unwrap();
|
|
||||||
let pity_s = status_bin
|
|
||||||
.rarity_status_map
|
|
||||||
.get(&common_properties.s_item_rarity)
|
|
||||||
.unwrap()
|
|
||||||
.pity;
|
|
||||||
let pity_a = status_bin
|
|
||||||
.rarity_status_map
|
|
||||||
.get(&common_properties.a_item_rarity)
|
|
||||||
.unwrap()
|
|
||||||
.pity;
|
|
||||||
|
|
||||||
let mut discount_ten_roll_prize: u32 = 0;
|
|
||||||
let mut discount_avaliable_num: u32 = 0;
|
|
||||||
let mut advanced_s_guarantee: u32 = 0;
|
|
||||||
let mut free_select_progress: u32 = 0;
|
|
||||||
let mut free_select_required_pull: u32 = 0;
|
|
||||||
let mut free_select_policy: Option<&FreeSelectItem> = None;
|
|
||||||
for discount_policy_tag in target_pool.discount_policy_tags.iter() {
|
|
||||||
if common_properties.newcomer_advanced_s_tag == *discount_policy_tag {
|
|
||||||
let policy = gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.advanced_guarantee_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
if status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap()
|
|
||||||
< &policy.use_limit
|
|
||||||
{
|
|
||||||
advanced_s_guarantee = policy.guarantee_pity - pity_s + 1;
|
|
||||||
}
|
|
||||||
} else if common_properties.ten_pull_discount_tag == *discount_policy_tag {
|
|
||||||
let policy = gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.ten_pull_discount_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
let discount_usage = status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
if discount_usage < &policy.use_limit {
|
|
||||||
discount_ten_roll_prize = policy.discounted_prize;
|
|
||||||
discount_avaliable_num = policy.use_limit - discount_usage;
|
|
||||||
}
|
|
||||||
} else if gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.free_select_map
|
|
||||||
.contains_key(discount_policy_tag)
|
|
||||||
{
|
|
||||||
let policy = gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.free_select_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
let free_select_demand_idx = usize::try_from(
|
|
||||||
*(status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(&policy.free_select_usage_record_tag)
|
|
||||||
.unwrap()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
if policy.milestones.len() <= free_select_demand_idx {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let free_select_actual_progress = status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(&policy.free_select_progress_record_tag)
|
|
||||||
.unwrap();
|
|
||||||
free_select_policy = Some(policy);
|
|
||||||
free_select_required_pull = policy
|
|
||||||
.milestones
|
|
||||||
.get(free_select_demand_idx)
|
|
||||||
.unwrap()
|
|
||||||
.to_owned();
|
|
||||||
free_select_progress = min(free_select_required_pull, *free_select_actual_progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut up_s_item_list: Vec<u32> = vec![];
|
|
||||||
let mut up_a_item_list: Vec<u32> = vec![];
|
|
||||||
let mut free_select_item_list: Vec<u32> = vec![];
|
|
||||||
let mut chooseable_up_list: Vec<u32> = vec![];
|
|
||||||
let mut chosen_up_item: u32 = 0;
|
|
||||||
let mut s_guarantee: u32 = 0;
|
|
||||||
let mut a_guarantee: u32 = 0;
|
|
||||||
for rarity_items in target_pool.gacha_items.iter() {
|
|
||||||
let mut chooseable_up_included_category_tags: Option<&HashSet<String>> = None;
|
|
||||||
let mut chooseable_policy_tag: Option<&String> = None;
|
|
||||||
for guarantee_policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
|
||||||
let category_guarantee_policy = gachaconf
|
|
||||||
.category_guarantee_policy_map
|
|
||||||
.get(guarantee_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
if !category_guarantee_policy.chooseable {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
chooseable_policy_tag = Some(guarantee_policy_tag);
|
|
||||||
chooseable_up_included_category_tags =
|
|
||||||
Some(&category_guarantee_policy.included_category_tags);
|
|
||||||
if let Some(item) = status_bin
|
|
||||||
.rarity_status_map
|
|
||||||
.get(&rarity_items.rarity)
|
|
||||||
.unwrap()
|
|
||||||
.categories_chosen_guarantee_item_map
|
|
||||||
.get(guarantee_policy_tag)
|
|
||||||
{
|
|
||||||
chosen_up_item = item.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (category_tag, category) in rarity_items.categories.iter() {
|
|
||||||
let probability_model = gachaconf
|
|
||||||
.probability_model_map
|
|
||||||
.get(&rarity_items.probability_model_tag)
|
|
||||||
.unwrap();
|
|
||||||
let maximum_pity = &probability_model.maximum_guarantee_pity;
|
|
||||||
if rarity_items.rarity == common_properties.s_item_rarity {
|
|
||||||
if category.is_promotional_items {
|
|
||||||
up_s_item_list = category.item_ids.clone();
|
|
||||||
}
|
|
||||||
// tracing::info!("pity_s: {pity_s}");
|
|
||||||
// thread 'tokio-runtime-worker' panicked at nap_gameserver\src\handlers\gacha.rs:369:31:
|
|
||||||
// attempt to subtract with overflow
|
|
||||||
s_guarantee = maximum_pity - min(pity_s, maximum_pity.clone()) + 1;
|
|
||||||
}
|
|
||||||
if rarity_items.rarity == common_properties.a_item_rarity {
|
|
||||||
if category.is_promotional_items {
|
|
||||||
up_a_item_list = category.item_ids.clone();
|
|
||||||
}
|
|
||||||
// tracing::info!("pity_a: {pity_a}");
|
|
||||||
a_guarantee = maximum_pity - min(pity_a, maximum_pity.clone()) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(val) = free_select_policy {
|
|
||||||
if val.rarity == rarity_items.rarity && val.category_tags.contains(category_tag)
|
|
||||||
{
|
|
||||||
free_select_item_list.append(&mut category.item_ids.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(tags) = chooseable_up_included_category_tags {
|
|
||||||
if tags.contains(category_tag) {
|
|
||||||
chooseable_up_list.append(&mut category.item_ids.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(_priority_policy_tag) = chooseable_policy_tag {
|
|
||||||
// if let Some(item) = status_bin
|
|
||||||
// .rarity_status_map
|
|
||||||
// .get(&rarity_items.rarity)
|
|
||||||
// .unwrap()
|
|
||||||
// .categories_chosen_guarantee_item_map
|
|
||||||
// .get(priority_policy_tag)
|
|
||||||
// {
|
|
||||||
if rarity_items.rarity == gachaconf.common_properties.s_item_rarity {
|
|
||||||
up_s_item_list = chooseable_up_list.clone();
|
|
||||||
} else if rarity_items.rarity == gachaconf.common_properties.a_item_rarity {
|
|
||||||
up_a_item_list = vec![];
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let need_item_info_list: Vec<NeedItemInfo> = vec![NeedItemInfo {
|
|
||||||
need_item_id: target_pool.cost_item_id,
|
|
||||||
need_item_count: 1,
|
|
||||||
}];
|
|
||||||
|
|
||||||
let mut result = Gacha {
|
|
||||||
gacha_schedule_id: target_pool.gacha_schedule_id,
|
|
||||||
gacha_parent_schedule_id: target_pool.gacha_parent_schedule_id,
|
|
||||||
gacha_type: target_pool.gacha_type,
|
|
||||||
start_timestamp: target_pool.start_time.timestamp(),
|
|
||||||
end_timestamp: target_pool.end_time.timestamp(),
|
|
||||||
discount_avaliable_num,
|
|
||||||
discount_ten_roll_prize,
|
|
||||||
advanced_s_guarantee,
|
|
||||||
s_guarantee,
|
|
||||||
a_guarantee,
|
|
||||||
need_item_info_list,
|
|
||||||
free_select_progress,
|
|
||||||
free_select_required_pull,
|
|
||||||
free_select_item_list,
|
|
||||||
chosen_up_item,
|
|
||||||
// nammdglepbk: 563,
|
|
||||||
// hgmcofcjmbg: 101,
|
|
||||||
// akggbhgkifd: chooseable_up_list.clone(),
|
|
||||||
chooseable_up_list,
|
|
||||||
..Gacha::default()
|
|
||||||
};
|
|
||||||
if up_s_item_list.len() > 0 {
|
|
||||||
result.up_s_item_list = up_s_item_list;
|
|
||||||
}
|
|
||||||
if up_a_item_list.len() > 0 {
|
|
||||||
result.up_a_item_list = up_a_item_list;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the actual item cost count (counting discount).
|
|
||||||
pub fn get_actual_cost_count<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
pull_count: &u32,
|
|
||||||
) -> u32 {
|
|
||||||
let gachaconf = global_gacha_config();
|
|
||||||
|
|
||||||
if *pull_count == 10 {
|
|
||||||
let discount_tag = &gachaconf.common_properties.ten_pull_discount_tag;
|
|
||||||
if target_pool.discount_policy_tags.contains(&discount_tag) {
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
let discount_policy = gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.ten_pull_discount_map
|
|
||||||
.get(discount_tag)
|
|
||||||
.unwrap();
|
|
||||||
let usage = status_bin.discount_usage_map.get_mut(discount_tag).unwrap();
|
|
||||||
if *usage < discount_policy.use_limit {
|
|
||||||
*usage += 1;
|
|
||||||
return discount_policy.discounted_prize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pull_count.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn request_free_agent<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
item_id: &ItemID,
|
|
||||||
) -> GachaAddedItemType {
|
|
||||||
let gachaconf = global_gacha_config();
|
|
||||||
let sharing_guarantee_category_tag = &target_pool.sharing_guarantee_info_category;
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(sharing_guarantee_category_tag)
|
|
||||||
.unwrap();
|
|
||||||
let item_id = item_id.value();
|
|
||||||
|
|
||||||
let mut free_select_policy: Option<&FreeSelectItem> = None;
|
|
||||||
let mut free_select_progress: u32 = 0;
|
|
||||||
let mut free_select_required_pull: u32 = 0;
|
|
||||||
for discount_policy_tag in target_pool.discount_policy_tags.iter() {
|
|
||||||
if gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.free_select_map
|
|
||||||
.contains_key(discount_policy_tag)
|
|
||||||
{
|
|
||||||
let policy = gachaconf
|
|
||||||
.discount_policies
|
|
||||||
.free_select_map
|
|
||||||
.get(discount_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
let free_select_demand_idx = usize::try_from(
|
|
||||||
*(status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(&policy.free_select_usage_record_tag)
|
|
||||||
.unwrap()),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
if policy.milestones.len() <= free_select_demand_idx {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let free_select_actual_progress = status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get(&policy.free_select_progress_record_tag)
|
|
||||||
.unwrap();
|
|
||||||
free_select_policy = Some(policy);
|
|
||||||
free_select_required_pull = policy
|
|
||||||
.milestones
|
|
||||||
.get(free_select_demand_idx)
|
|
||||||
.unwrap()
|
|
||||||
.to_owned();
|
|
||||||
free_select_progress = min(free_select_required_pull, *free_select_actual_progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let None = free_select_policy {
|
|
||||||
tracing::info!(
|
|
||||||
"refuse free agent because: pool of parent_schedule_id {} hasn't defined free agent discount yet (or used up chance)",
|
|
||||||
target_pool.gacha_parent_schedule_id
|
|
||||||
);
|
|
||||||
return GachaAddedItemType::None;
|
|
||||||
} else if free_select_progress < free_select_required_pull {
|
|
||||||
tracing::info!(
|
|
||||||
"refuse free agent because: use pulled {free_select_progress} (after last free agent) in parent_schedule_id {}, required {free_select_required_pull}",
|
|
||||||
target_pool.gacha_parent_schedule_id
|
|
||||||
);
|
|
||||||
return GachaAddedItemType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let free_select_policy = free_select_policy.unwrap();
|
|
||||||
let mut item_type: GachaAddedItemType = GachaAddedItemType::None;
|
|
||||||
for rarity_items in target_pool.gacha_items.iter() {
|
|
||||||
if rarity_items.rarity != free_select_policy.rarity {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (category_tag, category) in rarity_items.categories.iter() {
|
|
||||||
if !free_select_policy.category_tags.contains(category_tag) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if category.item_ids.contains(&item_id) {
|
|
||||||
item_type = category.item_type.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if item_type != GachaAddedItemType::None {
|
|
||||||
(*status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get_mut(&free_select_policy.free_select_usage_record_tag)
|
|
||||||
.unwrap()) += 1;
|
|
||||||
(*status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get_mut(&free_select_policy.free_select_progress_record_tag)
|
|
||||||
.unwrap()) -= free_select_required_pull;
|
|
||||||
}
|
|
||||||
item_type
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn choose_gacha_up<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
item_id: &ItemID,
|
|
||||||
) -> bool {
|
|
||||||
let gachaconf = global_gacha_config();
|
|
||||||
let item_id = item_id.value();
|
|
||||||
for rarity_items in target_pool.gacha_items.iter() {
|
|
||||||
for guarantee_policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
|
||||||
let category_guarantee_policy = gachaconf
|
|
||||||
.category_guarantee_policy_map
|
|
||||||
.get(guarantee_policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
if !category_guarantee_policy.chooseable {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut up_category: Option<&String> = None;
|
|
||||||
for (category_tag, category) in rarity_items.categories.iter() {
|
|
||||||
if category.item_ids.contains(&item_id) {
|
|
||||||
up_category = Some(category_tag);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let None = up_category {
|
|
||||||
continue;
|
|
||||||
};
|
|
||||||
let up_category = up_category.unwrap();
|
|
||||||
|
|
||||||
let progress_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap()
|
|
||||||
.rarity_status_map
|
|
||||||
.get_mut(&rarity_items.rarity)
|
|
||||||
.unwrap();
|
|
||||||
match progress_bin
|
|
||||||
.categories_chosen_guarantee_item_map
|
|
||||||
.entry(guarantee_policy_tag.clone())
|
|
||||||
{
|
|
||||||
Occupied(mut occupied_entry) => {
|
|
||||||
occupied_entry.insert(item_id);
|
|
||||||
}
|
|
||||||
Vacant(vacant_entry) => {
|
|
||||||
vacant_entry.insert(item_id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match progress_bin
|
|
||||||
.categories_chosen_guarantee_category_map
|
|
||||||
.entry(up_category.clone())
|
|
||||||
{
|
|
||||||
Occupied(mut occupied_entry) => {
|
|
||||||
occupied_entry.insert(up_category.clone());
|
|
||||||
}
|
|
||||||
Vacant(vacant_entry) => {
|
|
||||||
vacant_entry.insert(up_category.clone());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +1,20 @@
|
||||||
use super::record::*;
|
|
||||||
use super::stat::*;
|
|
||||||
use data::gacha;
|
use data::gacha;
|
||||||
use data::gacha::gacha_config::*;
|
use data::gacha::gacha_config::*;
|
||||||
use data::tables::ItemID;
|
use proto::*;
|
||||||
|
|
||||||
use chrono::{DateTime, Local};
|
use chrono::{DateTime, Local};
|
||||||
use proto::GachaModelBin;
|
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::hash::{BuildHasher, Hash};
|
use std::hash::{BuildHasher, Hash};
|
||||||
|
|
||||||
pub struct GachaModel {
|
pub struct GachaModel {
|
||||||
pub gacha_status_map: HashMap<String, GachaStatus>,
|
pub gacha_bin: GachaModelBin,
|
||||||
pub gacha_records: Vec<GachaRecord>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GachaModel {
|
impl Default for GachaModel {
|
||||||
fn default() -> GachaModel {
|
fn default() -> GachaModel {
|
||||||
let result = GachaModel {
|
let result = GachaModel {
|
||||||
gacha_status_map: HashMap::new(),
|
gacha_bin: GachaModelBin::default(),
|
||||||
gacha_records: vec![],
|
|
||||||
};
|
};
|
||||||
result.post_deserialize()
|
result.post_deserialize()
|
||||||
}
|
}
|
||||||
|
@ -27,37 +22,19 @@ impl Default for GachaModel {
|
||||||
|
|
||||||
impl GachaModel {
|
impl GachaModel {
|
||||||
pub fn from_bin(gacha_bin: GachaModelBin) -> Self {
|
pub fn from_bin(gacha_bin: GachaModelBin) -> Self {
|
||||||
let result = Self {
|
let result = Self { gacha_bin };
|
||||||
gacha_status_map: gacha_bin
|
|
||||||
.gacha_status_map
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k, GachaStatus::from_bin(v)))
|
|
||||||
.collect(),
|
|
||||||
gacha_records: gacha_bin
|
|
||||||
.gacha_records
|
|
||||||
.into_iter()
|
|
||||||
.map(|x| GachaRecord::from_bin(x))
|
|
||||||
.collect(),
|
|
||||||
};
|
|
||||||
result.post_deserialize()
|
result.post_deserialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_bin(&self) -> GachaModelBin {
|
pub fn to_bin(&self) -> GachaModelBin {
|
||||||
GachaModelBin {
|
self.gacha_bin.clone()
|
||||||
gacha_status_map: self
|
|
||||||
.gacha_status_map
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.to_bin()))
|
|
||||||
.collect(),
|
|
||||||
gacha_records: self.gacha_records.iter().map(|x| x.to_bin()).collect(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_deserialize(mut self) -> GachaModel {
|
pub fn post_deserialize(mut self) -> GachaModel {
|
||||||
let gachaconf = gacha::global_gacha_config();
|
let gachaconf = gacha::global_gacha_config();
|
||||||
for gacha_pool in gachaconf.character_gacha_pool_list.iter() {
|
for gacha_pool in gachaconf.character_gacha_pool_list.iter() {
|
||||||
let mut gacha_status_map = &mut self.gacha_status_map;
|
let gacha_comp_bin = &mut self.gacha_bin;
|
||||||
|
let mut gacha_status_map = &mut gacha_comp_bin.gacha_status_map;
|
||||||
let status_bin = get_or_add(
|
let status_bin = get_or_add(
|
||||||
&mut gacha_status_map,
|
&mut gacha_status_map,
|
||||||
&gacha_pool.sharing_guarantee_info_category,
|
&gacha_pool.sharing_guarantee_info_category,
|
||||||
|
@ -120,11 +97,11 @@ impl GachaModel {
|
||||||
&'bin mut self,
|
&'bin mut self,
|
||||||
pull_time: &DateTime<Local>,
|
pull_time: &DateTime<Local>,
|
||||||
target_pool: &'conf CharacterGachaPool,
|
target_pool: &'conf CharacterGachaPool,
|
||||||
) -> GachaRecord {
|
) -> GachaRecordBin {
|
||||||
|
let mut gacha_bin = &mut self.gacha_bin;
|
||||||
let (rarity_items, progress_bin, status_bin, probability_model) =
|
let (rarity_items, progress_bin, status_bin, probability_model) =
|
||||||
self.determine_rarity(target_pool);
|
determine_rarity(&gacha_bin, target_pool);
|
||||||
let (category_tag, category) =
|
let (category_tag, category) = determine_category(rarity_items, progress_bin, target_pool);
|
||||||
self.determine_category(rarity_items, progress_bin, target_pool);
|
|
||||||
let result = determine_gacha_result(
|
let result = determine_gacha_result(
|
||||||
pull_time,
|
pull_time,
|
||||||
category,
|
category,
|
||||||
|
@ -133,19 +110,29 @@ impl GachaModel {
|
||||||
progress_bin,
|
progress_bin,
|
||||||
rarity_items,
|
rarity_items,
|
||||||
);
|
);
|
||||||
self.update_pity(rarity_items, probability_model, target_pool);
|
update_pity(&mut gacha_bin, rarity_items, probability_model, target_pool);
|
||||||
self.update_category_guarantee_info(rarity_items, &category_tag, target_pool);
|
update_category_guarantee_info(&mut gacha_bin, rarity_items, &category_tag, target_pool);
|
||||||
self.update_discount(target_pool, &category_tag, rarity_items);
|
update_discount(&mut gacha_bin, target_pool, &category_tag, rarity_items);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_or_add<'a, K: Eq + PartialEq + Hash + Clone, V: Default, S: BuildHasher>(
|
||||||
|
map: &'a mut HashMap<K, V, S>,
|
||||||
|
key: &K,
|
||||||
|
) -> &'a mut V {
|
||||||
|
if !map.contains_key(key) {
|
||||||
|
map.insert(key.clone(), V::default());
|
||||||
|
}
|
||||||
|
map.get_mut(key).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
fn rand_rarity<'bin, 'conf>(
|
fn rand_rarity<'bin, 'conf>(
|
||||||
&'bin self,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
target_pool: &'conf CharacterGachaPool,
|
||||||
status_bin: &'bin GachaStatus,
|
status_bin: &'bin GachaStatusBin,
|
||||||
) -> (
|
) -> (
|
||||||
&'conf GachaAvailableItemsInfo,
|
&'conf GachaAvailableItemsInfo,
|
||||||
&'bin GachaProgress,
|
&'bin GachaProgressBin,
|
||||||
&'conf ProbabilityModel,
|
&'conf ProbabilityModel,
|
||||||
) {
|
) {
|
||||||
let gachaconf = gacha::global_gacha_config();
|
let gachaconf = gacha::global_gacha_config();
|
||||||
|
@ -168,16 +155,16 @@ impl GachaModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_rarity<'bin, 'conf>(
|
fn determine_rarity<'bin, 'conf>(
|
||||||
&'bin self,
|
gacha_bin: &'bin GachaModelBin,
|
||||||
target_pool: &'conf CharacterGachaPool,
|
target_pool: &'conf CharacterGachaPool,
|
||||||
) -> (
|
) -> (
|
||||||
&'conf GachaAvailableItemsInfo,
|
&'conf GachaAvailableItemsInfo,
|
||||||
&'bin GachaProgress,
|
&'bin GachaProgressBin,
|
||||||
&'bin GachaStatus,
|
&'bin GachaStatusBin,
|
||||||
&'conf ProbabilityModel,
|
&'conf ProbabilityModel,
|
||||||
) {
|
) {
|
||||||
let gachaconf = gacha::global_gacha_config();
|
let gachaconf = gacha::global_gacha_config();
|
||||||
let status_bin = self
|
let status_bin = gacha_bin
|
||||||
.gacha_status_map
|
.gacha_status_map
|
||||||
.get(&target_pool.sharing_guarantee_info_category)
|
.get(&target_pool.sharing_guarantee_info_category)
|
||||||
.expect(&format!(
|
.expect(&format!(
|
||||||
|
@ -185,7 +172,7 @@ impl GachaModel {
|
||||||
target_pool.sharing_guarantee_info_category
|
target_pool.sharing_guarantee_info_category
|
||||||
));
|
));
|
||||||
let (mut rarity_items, mut progress_bin, mut probability_model) =
|
let (mut rarity_items, mut progress_bin, mut probability_model) =
|
||||||
self.rand_rarity(target_pool, &status_bin);
|
rand_rarity(target_pool, &status_bin);
|
||||||
|
|
||||||
// We should take AdvancedGuarantee discount into consideration.
|
// We should take AdvancedGuarantee discount into consideration.
|
||||||
for discount_tag in target_pool.discount_policy_tags.iter() {
|
for discount_tag in target_pool.discount_policy_tags.iter() {
|
||||||
|
@ -208,7 +195,8 @@ impl GachaModel {
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let higher_progress_bin = status_bin
|
let higher_progress_bin =
|
||||||
|
status_bin
|
||||||
.rarity_status_map
|
.rarity_status_map
|
||||||
.get(&discount.rarity)
|
.get(&discount.rarity)
|
||||||
.expect(&format!(
|
.expect(&format!(
|
||||||
|
@ -238,9 +226,8 @@ impl GachaModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_category<'bin, 'conf>(
|
fn determine_category<'bin, 'conf>(
|
||||||
&'bin self,
|
|
||||||
rarity_items: &'conf GachaAvailableItemsInfo,
|
rarity_items: &'conf GachaAvailableItemsInfo,
|
||||||
progress_bin: &'bin GachaProgress,
|
progress_bin: &'bin GachaProgressBin,
|
||||||
target_pool: &'conf CharacterGachaPool,
|
target_pool: &'conf CharacterGachaPool,
|
||||||
) -> (String, &'conf GachaCategoryInfo) {
|
) -> (String, &'conf GachaCategoryInfo) {
|
||||||
let gachaconf = gacha::global_gacha_config();
|
let gachaconf = gacha::global_gacha_config();
|
||||||
|
@ -326,138 +313,14 @@ impl GachaModel {
|
||||||
panic!("No category is chosen.");
|
panic!("No category is chosen.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_pity<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
rarity_items: &'conf GachaAvailableItemsInfo,
|
|
||||||
probability_model: &'conf ProbabilityModel,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
) {
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
for (rarity, rarity_status) in status_bin.rarity_status_map.iter_mut() {
|
|
||||||
if (rarity == &rarity_items.rarity)
|
|
||||||
|| (probability_model.clear_status_on_higher_rarity_pulled
|
|
||||||
&& rarity < &rarity_items.rarity)
|
|
||||||
{
|
|
||||||
rarity_status.pity = 1;
|
|
||||||
} else {
|
|
||||||
rarity_status.pity += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_category_guarantee_info<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
rarity_items: &'conf GachaAvailableItemsInfo,
|
|
||||||
category_tag: &String,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
) {
|
|
||||||
let gachaconf = gacha::global_gacha_config();
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
let progress_bin = status_bin
|
|
||||||
.rarity_status_map
|
|
||||||
.get_mut(&rarity_items.rarity)
|
|
||||||
.unwrap();
|
|
||||||
for policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
|
||||||
let policy = gachaconf
|
|
||||||
.category_guarantee_policy_map
|
|
||||||
.get(policy_tag)
|
|
||||||
.unwrap();
|
|
||||||
// TODO: Chooseable guarantee not implemented
|
|
||||||
let prev_failure = progress_bin
|
|
||||||
.categories_progress_map
|
|
||||||
.get_mut(policy_tag)
|
|
||||||
.expect(&format!(
|
|
||||||
"post_deserialize forgot StatusBin/rarity_status_map[{}]/categories_progress_map: {}",
|
|
||||||
rarity_items.rarity, policy_tag
|
|
||||||
));
|
|
||||||
if policy.included_category_tags.contains(category_tag) {
|
|
||||||
*prev_failure = 0;
|
|
||||||
} else {
|
|
||||||
*prev_failure += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_discount<'bin, 'conf>(
|
|
||||||
&'bin mut self,
|
|
||||||
target_pool: &'conf CharacterGachaPool,
|
|
||||||
category_tag: &String,
|
|
||||||
rarity_items: &GachaAvailableItemsInfo,
|
|
||||||
) {
|
|
||||||
let gachaconf = gacha::global_gacha_config();
|
|
||||||
for (policy_tag, policy) in gachaconf.discount_policies.must_gain_item_map.iter() {
|
|
||||||
if *category_tag != policy.category_tag {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
let usage = status_bin.discount_usage_map.get_mut(policy_tag).unwrap();
|
|
||||||
if *usage < policy.use_limit {
|
|
||||||
*usage += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (policy_tag, policy) in gachaconf.discount_policies.advanced_guarantee_map.iter() {
|
|
||||||
if rarity_items.rarity != policy.rarity {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
let usage = status_bin.discount_usage_map.get_mut(policy_tag).unwrap();
|
|
||||||
if *usage < policy.use_limit {
|
|
||||||
*usage += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (policy_tag, policy) in gachaconf.discount_policies.free_select_map.iter() {
|
|
||||||
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let status_bin = self
|
|
||||||
.gacha_status_map
|
|
||||||
.get_mut(&target_pool.sharing_guarantee_info_category)
|
|
||||||
.unwrap();
|
|
||||||
let progress = status_bin
|
|
||||||
.discount_usage_map
|
|
||||||
.get_mut(&policy.free_select_progress_record_tag)
|
|
||||||
.unwrap();
|
|
||||||
*progress += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_or_add<'a, K: Eq + PartialEq + Hash + Clone, V: Default, S: BuildHasher>(
|
|
||||||
map: &'a mut HashMap<K, V, S>,
|
|
||||||
key: &K,
|
|
||||||
) -> &'a mut V {
|
|
||||||
if !map.contains_key(key) {
|
|
||||||
map.insert(key.clone(), V::default());
|
|
||||||
}
|
|
||||||
map.get_mut(key).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn determine_gacha_result<'bin, 'conf>(
|
fn determine_gacha_result<'bin, 'conf>(
|
||||||
pull_time: &DateTime<Local>,
|
pull_time: &DateTime<Local>,
|
||||||
category: &'conf GachaCategoryInfo,
|
category: &'conf GachaCategoryInfo,
|
||||||
target_pool: &'conf CharacterGachaPool,
|
target_pool: &'conf CharacterGachaPool,
|
||||||
status_bin: &'bin GachaStatus,
|
status_bin: &'bin GachaStatusBin,
|
||||||
progress_bin: &'bin GachaProgress,
|
progress_bin: &'bin GachaProgressBin,
|
||||||
rarity_items: &'conf GachaAvailableItemsInfo,
|
rarity_items: &'conf GachaAvailableItemsInfo,
|
||||||
) -> GachaRecord {
|
) -> GachaRecordBin {
|
||||||
let gachaconf = gacha::global_gacha_config();
|
let gachaconf = gacha::global_gacha_config();
|
||||||
let item_pool_len = category.item_ids.len() as u32;
|
let item_pool_len = category.item_ids.len() as u32;
|
||||||
let mut item_id: Option<&u32> = None;
|
let mut item_id: Option<&u32> = None;
|
||||||
|
@ -498,7 +361,7 @@ fn determine_gacha_result<'bin, 'conf>(
|
||||||
.get(rand::thread_rng().gen_range(0..item_pool_len) as usize)
|
.get(rand::thread_rng().gen_range(0..item_pool_len) as usize)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
let mut extra_item_id: Option<ItemID> = None;
|
let mut extra_item_id: u32 = 0;
|
||||||
let mut extra_item_count: u32 = 0;
|
let mut extra_item_count: u32 = 0;
|
||||||
|
|
||||||
for extra_items_policy_tag in rarity_items.extra_items_policy_tags.iter() {
|
for extra_items_policy_tag in rarity_items.extra_items_policy_tags.iter() {
|
||||||
|
@ -509,23 +372,134 @@ fn determine_gacha_result<'bin, 'conf>(
|
||||||
// TODO: apply_on_owned_count in a context with bag
|
// TODO: apply_on_owned_count in a context with bag
|
||||||
// TODO: That's what RoleModel should do, not me.
|
// TODO: That's what RoleModel should do, not me.
|
||||||
if extra_items_policy.apply_on_owned_count == 0 {
|
if extra_items_policy.apply_on_owned_count == 0 {
|
||||||
extra_item_id = ItemID::new(extra_items_policy.id);
|
extra_item_id = extra_items_policy.id;
|
||||||
extra_item_count = extra_items_policy.count;
|
extra_item_count = extra_items_policy.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let extra_resources = match extra_item_id {
|
let extra_item_bin = GachaExtraItemBin {
|
||||||
Some(item_id) => Some(GachaExtraResources {
|
extra_item_id,
|
||||||
extra_item_id: item_id,
|
|
||||||
extra_item_count,
|
extra_item_count,
|
||||||
}),
|
currently_gained: 0,
|
||||||
None => None,
|
|
||||||
};
|
};
|
||||||
GachaRecord {
|
GachaRecordBin {
|
||||||
pull_timestamp: pull_time.timestamp(),
|
pull_timestamp: pull_time.timestamp(),
|
||||||
obtained_item_id: ItemID::new_unchecked(item_id.clone()),
|
obtained_item_id: item_id.clone(),
|
||||||
gacha_id: target_pool.gacha_schedule_id.clone(),
|
gacha_id: target_pool.gacha_schedule_id.clone(),
|
||||||
progress_map: status_bin.rarity_status_map.clone(),
|
progress_map: status_bin.rarity_status_map.clone(),
|
||||||
extra_resources,
|
extra_item_bin: Some(extra_item_bin),
|
||||||
item_type: category.item_type.clone(),
|
item_type: category.item_type.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_pity<'bin, 'conf>(
|
||||||
|
gacha_bin: &'bin mut GachaModelBin,
|
||||||
|
rarity_items: &'conf GachaAvailableItemsInfo,
|
||||||
|
probability_model: &'conf ProbabilityModel,
|
||||||
|
target_pool: &'conf CharacterGachaPool,
|
||||||
|
) {
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
for (rarity, rarity_status) in status_bin.rarity_status_map.iter_mut() {
|
||||||
|
if (rarity == &rarity_items.rarity)
|
||||||
|
|| (probability_model.clear_status_on_higher_rarity_pulled
|
||||||
|
&& rarity < &rarity_items.rarity)
|
||||||
|
{
|
||||||
|
rarity_status.pity = 1;
|
||||||
|
} else {
|
||||||
|
rarity_status.pity += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_category_guarantee_info<'bin, 'conf>(
|
||||||
|
gacha_bin: &'bin mut GachaModelBin,
|
||||||
|
rarity_items: &'conf GachaAvailableItemsInfo,
|
||||||
|
category_tag: &String,
|
||||||
|
target_pool: &'conf CharacterGachaPool,
|
||||||
|
) {
|
||||||
|
let gachaconf = gacha::global_gacha_config();
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
let progress_bin = status_bin
|
||||||
|
.rarity_status_map
|
||||||
|
.get_mut(&rarity_items.rarity)
|
||||||
|
.unwrap();
|
||||||
|
for policy_tag in rarity_items.category_guarantee_policy_tags.iter() {
|
||||||
|
let policy = gachaconf
|
||||||
|
.category_guarantee_policy_map
|
||||||
|
.get(policy_tag)
|
||||||
|
.unwrap();
|
||||||
|
// TODO: Chooseable guarantee not implemented
|
||||||
|
let prev_failure = progress_bin
|
||||||
|
.categories_progress_map
|
||||||
|
.get_mut(policy_tag)
|
||||||
|
.expect(&format!(
|
||||||
|
"post_deserialize forgot StatusBin/rarity_status_map[{}]/categories_progress_map: {}",
|
||||||
|
rarity_items.rarity, policy_tag
|
||||||
|
));
|
||||||
|
if policy.included_category_tags.contains(category_tag) {
|
||||||
|
*prev_failure = 0;
|
||||||
|
} else {
|
||||||
|
*prev_failure += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_discount<'bin, 'conf>(
|
||||||
|
gacha_bin: &'bin mut GachaModelBin,
|
||||||
|
target_pool: &'conf CharacterGachaPool,
|
||||||
|
category_tag: &String,
|
||||||
|
rarity_items: &GachaAvailableItemsInfo,
|
||||||
|
) {
|
||||||
|
let gachaconf = gacha::global_gacha_config();
|
||||||
|
for (policy_tag, policy) in gachaconf.discount_policies.must_gain_item_map.iter() {
|
||||||
|
if *category_tag != policy.category_tag {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
let usage = status_bin.discount_usage_map.get_mut(policy_tag).unwrap();
|
||||||
|
if *usage < policy.use_limit {
|
||||||
|
*usage += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (policy_tag, policy) in gachaconf.discount_policies.advanced_guarantee_map.iter() {
|
||||||
|
if rarity_items.rarity != policy.rarity {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
let usage = status_bin.discount_usage_map.get_mut(policy_tag).unwrap();
|
||||||
|
if *usage < policy.use_limit {
|
||||||
|
*usage += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (policy_tag, policy) in gachaconf.discount_policies.free_select_map.iter() {
|
||||||
|
if !target_pool.discount_policy_tags.contains(policy_tag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let status_bin = gacha_bin
|
||||||
|
.gacha_status_map
|
||||||
|
.get_mut(&target_pool.sharing_guarantee_info_category)
|
||||||
|
.unwrap();
|
||||||
|
let progress = status_bin
|
||||||
|
.discount_usage_map
|
||||||
|
.get_mut(&policy.free_select_progress_record_tag)
|
||||||
|
.unwrap();
|
||||||
|
*progress += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
mod client_op;
|
|
||||||
mod gacha_model;
|
mod gacha_model;
|
||||||
mod record;
|
mod record;
|
||||||
mod stat;
|
|
||||||
|
|
||||||
pub use gacha_model::GachaModel;
|
pub use gacha_model::GachaModel;
|
|
@ -1,85 +0,0 @@
|
||||||
use data::gacha::gacha_config::*;
|
|
||||||
use data::tables::ItemID;
|
|
||||||
|
|
||||||
use proto::{GachaExtraItemBin, GachaRecordBin};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use super::stat::*;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct GachaExtraResources {
|
|
||||||
pub extra_item_id: ItemID,
|
|
||||||
pub extra_item_count: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GachaExtraResources {
|
|
||||||
pub fn from_bin_opt(bin_opt: Option<GachaExtraItemBin>) -> Option<Self> {
|
|
||||||
match bin_opt {
|
|
||||||
None => None,
|
|
||||||
Some(bin) => {
|
|
||||||
let item_id_opt = ItemID::new(bin.extra_item_id);
|
|
||||||
match item_id_opt {
|
|
||||||
None => None,
|
|
||||||
Some(extra_item_id) => Some(Self {
|
|
||||||
extra_item_id,
|
|
||||||
extra_item_count: bin.extra_item_count,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bin_opt(opt: &Option<Self>) -> Option<GachaExtraItemBin> {
|
|
||||||
match opt {
|
|
||||||
None => None,
|
|
||||||
Some(this) => Some(GachaExtraItemBin {
|
|
||||||
extra_item_id: this.extra_item_id.value(),
|
|
||||||
extra_item_count: this.extra_item_count.clone(),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct GachaRecord {
|
|
||||||
pub pull_timestamp: i64,
|
|
||||||
pub obtained_item_id: ItemID,
|
|
||||||
pub gacha_id: u32,
|
|
||||||
/// The progress BEFORE this gacha is performed. key is rarity.
|
|
||||||
pub progress_map: HashMap<u32, GachaProgress>,
|
|
||||||
pub extra_resources: Option<GachaExtraResources>,
|
|
||||||
pub item_type: GachaAddedItemType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GachaRecord {
|
|
||||||
pub fn from_bin(bin: GachaRecordBin) -> Self {
|
|
||||||
Self {
|
|
||||||
pull_timestamp: bin.pull_timestamp,
|
|
||||||
obtained_item_id: ItemID::new_unchecked(bin.obtained_item_id),
|
|
||||||
gacha_id: bin.gacha_id,
|
|
||||||
progress_map: bin
|
|
||||||
.progress_map
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k, GachaProgress::from_bin(v)))
|
|
||||||
.collect(),
|
|
||||||
extra_resources: GachaExtraResources::from_bin_opt(bin.extra_item_bin),
|
|
||||||
item_type: GachaAddedItemType::from(bin.item_type),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bin(&self) -> GachaRecordBin {
|
|
||||||
GachaRecordBin {
|
|
||||||
pull_timestamp: self.pull_timestamp.clone(),
|
|
||||||
obtained_item_id: self.obtained_item_id.value(),
|
|
||||||
gacha_id: self.gacha_id.clone(),
|
|
||||||
progress_map: self
|
|
||||||
.progress_map
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.to_bin()))
|
|
||||||
.collect(),
|
|
||||||
extra_item_bin: GachaExtraResources::to_bin_opt(&self.extra_resources),
|
|
||||||
item_type: self.item_type.clone().into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
use proto::*;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct GachaProgress {
|
|
||||||
/// The pity (counting how many pulls) of this pull (in previous record) or the next pull (in status).
|
|
||||||
pub pity: u32,
|
|
||||||
/// The failure times of this category.
|
|
||||||
pub categories_progress_map: HashMap<String, u32>,
|
|
||||||
/// The selected priority (category) for a Chooseable category.
|
|
||||||
pub categories_chosen_guarantee_category_map: HashMap<String, String>,
|
|
||||||
/// The selectedpriority (a specified item) for a Chooseable category.
|
|
||||||
pub categories_chosen_guarantee_item_map: HashMap<String, u32>,
|
|
||||||
/// The failure times for selected priority (a specified item).
|
|
||||||
pub categories_chosen_guarantee_progress_map: HashMap<String, u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GachaProgress {
|
|
||||||
pub fn from_bin(bin: GachaProgressBin) -> Self {
|
|
||||||
Self {
|
|
||||||
pity: bin.pity,
|
|
||||||
categories_progress_map: bin.categories_progress_map,
|
|
||||||
categories_chosen_guarantee_category_map: bin.categories_chosen_guarantee_category_map,
|
|
||||||
categories_chosen_guarantee_item_map: bin.categories_chosen_guarantee_item_map,
|
|
||||||
categories_chosen_guarantee_progress_map: bin.categories_chosen_guarantee_progress_map,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bin(&self) -> GachaProgressBin {
|
|
||||||
GachaProgressBin {
|
|
||||||
pity: self.pity,
|
|
||||||
categories_progress_map: self.categories_progress_map.clone(),
|
|
||||||
categories_chosen_guarantee_category_map: self
|
|
||||||
.categories_chosen_guarantee_category_map
|
|
||||||
.clone(),
|
|
||||||
categories_chosen_guarantee_item_map: self.categories_chosen_guarantee_item_map.clone(),
|
|
||||||
categories_chosen_guarantee_progress_map: self
|
|
||||||
.categories_chosen_guarantee_progress_map
|
|
||||||
.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
|
||||||
pub struct GachaStatus {
|
|
||||||
pub rarity_status_map: HashMap<u32, GachaProgress>,
|
|
||||||
pub discount_usage_map: HashMap<String, u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GachaStatus {
|
|
||||||
pub fn from_bin(bin: GachaStatusBin) -> Self {
|
|
||||||
Self {
|
|
||||||
rarity_status_map: bin
|
|
||||||
.rarity_status_map
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k, GachaProgress::from_bin(v)))
|
|
||||||
.collect(),
|
|
||||||
discount_usage_map: bin.discount_usage_map,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_bin(&self) -> GachaStatusBin {
|
|
||||||
GachaStatusBin {
|
|
||||||
rarity_status_map: self
|
|
||||||
.rarity_status_map
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.to_bin()))
|
|
||||||
.collect(),
|
|
||||||
discount_usage_map: self.discount_usage_map.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +1,26 @@
|
||||||
use common::util;
|
use common::util;
|
||||||
use data::tables::{
|
use data::tables::{ArchiveBattleQuestID, TrainingQuestID};
|
||||||
self, ArchiveBattleQuestID, BattleEventConfigID, HollowQuestID, TrainingQuestID,
|
|
||||||
};
|
|
||||||
use proto::{DungeonInfo, DungeonItemData, FightSceneInfo, SceneInfo, WeatherPoolInfo};
|
use proto::{DungeonInfo, DungeonItemData, FightSceneInfo, SceneInfo, WeatherPoolInfo};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::logic::{
|
use crate::logic::{
|
||||||
battle::{
|
battle::{EquippedBuddyDataItem, InLevelAvatarDataItem, TeamDataItem},
|
||||||
drop::FightDropPool,
|
ELocalPlayType, ESceneType, TimePeriodType, WeatherType,
|
||||||
unit::{AvatarUnit, BuddyUnit},
|
|
||||||
BuddyParam, DungeonQuestManager, TeamDataItem,
|
|
||||||
},
|
|
||||||
BuddyTeamType, EHollowQuestType, ELocalPlayType, ESceneType, TimePeriodType, WeatherType,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::NapGameMode;
|
use super::NapGameMode;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum HollowGameError {
|
pub enum HollowGameError {}
|
||||||
#[error("Quest ({0}) type is not supported: {1:?}")]
|
|
||||||
QuestTypeNotSupported(u32, EHollowQuestType),
|
|
||||||
#[error("Battle group not found, quest id: {0}")]
|
|
||||||
BattleGroupNotFound(u32),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct HollowGame {
|
pub struct HollowGame {
|
||||||
pub quest_id: u32,
|
pub quest_id: u32,
|
||||||
pub battle_event_id: BattleEventConfigID,
|
pub battle_event_id: u32,
|
||||||
pub time_period: TimePeriodType,
|
pub time_period: TimePeriodType,
|
||||||
pub weather: WeatherType,
|
pub weather: WeatherType,
|
||||||
pub play_type: ELocalPlayType,
|
pub play_type: ELocalPlayType,
|
||||||
pub start_timestamp: i64,
|
pub start_timestamp: i64,
|
||||||
pub team_data: TeamDataItem,
|
pub team_data: TeamDataItem,
|
||||||
pub fight_drop_pool: FightDropPool,
|
|
||||||
pub quest_manager: DungeonQuestManager,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HollowGame {
|
impl HollowGame {
|
||||||
|
@ -51,9 +38,7 @@ impl HollowGame {
|
||||||
weather: WeatherType::SunShine,
|
weather: WeatherType::SunShine,
|
||||||
start_timestamp: util::cur_timestamp() as i64,
|
start_timestamp: util::cur_timestamp() as i64,
|
||||||
play_type,
|
play_type,
|
||||||
team_data: TeamDataItem::new(avatars, &[]),
|
team_data: TeamDataItem::new(avatars, 0),
|
||||||
fight_drop_pool: FightDropPool::new(template.battle_event_id),
|
|
||||||
quest_manager: DungeonQuestManager::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,66 +57,9 @@ impl HollowGame {
|
||||||
weather: WeatherType::SunShine,
|
weather: WeatherType::SunShine,
|
||||||
start_timestamp: util::cur_timestamp() as i64,
|
start_timestamp: util::cur_timestamp() as i64,
|
||||||
play_type,
|
play_type,
|
||||||
team_data: TeamDataItem::new(
|
team_data: TeamDataItem::new(avatars, buddy_id),
|
||||||
avatars,
|
|
||||||
&(buddy_id != 0)
|
|
||||||
.then_some(vec![BuddyParam(buddy_id, BuddyTeamType::Fighting)])
|
|
||||||
.unwrap_or_default(),
|
|
||||||
),
|
|
||||||
fight_drop_pool: FightDropPool::new(template.battle_event_id),
|
|
||||||
quest_manager: DungeonQuestManager::default(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_pure_hollow_battle(
|
|
||||||
quest_id: HollowQuestID,
|
|
||||||
avatars: &[u32],
|
|
||||||
buddy_id: u32,
|
|
||||||
time_period: TimePeriodType,
|
|
||||||
weather: WeatherType,
|
|
||||||
) -> Result<Self, HollowGameError> {
|
|
||||||
let template = quest_id.template();
|
|
||||||
if template.chess_board_id != 0 {
|
|
||||||
return Err(HollowGameError::QuestTypeNotSupported(
|
|
||||||
template.id.value(),
|
|
||||||
EHollowQuestType::from(template.hollow_quest_type),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(battle_group) = tables::battle_group_config_template_tb::iter()
|
|
||||||
.find(|tmpl| tmpl.quest_id == template.id.value())
|
|
||||||
else {
|
|
||||||
return Err(HollowGameError::BattleGroupNotFound(template.id.value()));
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
quest_id: template.id.value(),
|
|
||||||
battle_event_id: battle_group.battle_event_id,
|
|
||||||
time_period,
|
|
||||||
weather,
|
|
||||||
start_timestamp: util::cur_timestamp() as i64,
|
|
||||||
play_type: Self::get_play_type_by_quest_type(EHollowQuestType::from(
|
|
||||||
template.hollow_quest_type,
|
|
||||||
)),
|
|
||||||
team_data: TeamDataItem::new(
|
|
||||||
avatars,
|
|
||||||
&(buddy_id != 0)
|
|
||||||
.then_some(vec![BuddyParam(buddy_id, BuddyTeamType::Fighting)])
|
|
||||||
.unwrap_or_default(),
|
|
||||||
),
|
|
||||||
fight_drop_pool: FightDropPool::new(battle_group.battle_event_id),
|
|
||||||
quest_manager: DungeonQuestManager::new_for_battle_group(battle_group.id),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_play_type_by_quest_type(quest_type: EHollowQuestType) -> ELocalPlayType {
|
|
||||||
match quest_type {
|
|
||||||
EHollowQuestType::NormalBattle => ELocalPlayType::PureHollowBattle,
|
|
||||||
EHollowQuestType::BossRushBattle => ELocalPlayType::BossRushBattle,
|
|
||||||
EHollowQuestType::DifficutyBattle => ELocalPlayType::PureHollowBattleHardmode,
|
|
||||||
_ => ELocalPlayType::PureHollowBattle,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NapGameMode for HollowGame {
|
impl NapGameMode for HollowGame {
|
||||||
|
@ -142,16 +70,14 @@ impl NapGameMode for HollowGame {
|
||||||
fn scene_info(&self) -> Option<SceneInfo> {
|
fn scene_info(&self) -> Option<SceneInfo> {
|
||||||
Some(SceneInfo {
|
Some(SceneInfo {
|
||||||
scene_type: self.scene_type() as u32,
|
scene_type: self.scene_type() as u32,
|
||||||
battle_event_id: self.battle_event_id.value(),
|
battle_event_id: self.battle_event_id,
|
||||||
play_type: self.play_type as u32,
|
play_type: self.play_type as u32,
|
||||||
fight_scene_info: Some(FightSceneInfo {
|
fight_scene_info: Some(FightSceneInfo {
|
||||||
nmhdkmcabjg: true,
|
|
||||||
weather_pool: Some(WeatherPoolInfo {
|
weather_pool: Some(WeatherPoolInfo {
|
||||||
time_period: self.time_period.to_string(),
|
time_period: self.time_period.to_string(),
|
||||||
weather: self.weather.to_string(),
|
weather: self.weather.to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
fight_drop_info: Some(self.fight_drop_pool.to_client()),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -167,15 +93,14 @@ impl NapGameMode for HollowGame {
|
||||||
.team_data
|
.team_data
|
||||||
.avatar_member_list
|
.avatar_member_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(AvatarUnit::to_client)
|
.map(InLevelAvatarDataItem::to_client)
|
||||||
.collect(),
|
.collect(),
|
||||||
buddy_list: self
|
buddy_list: self
|
||||||
.team_data
|
.team_data
|
||||||
.equipped_buddy_list
|
.equipped_buddy_list
|
||||||
.iter()
|
.iter()
|
||||||
.map(BuddyUnit::to_client)
|
.map(EquippedBuddyDataItem::to_client)
|
||||||
.collect(),
|
.collect(),
|
||||||
dungeon_quest_info: Some(self.quest_manager.to_client()),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
use common::util;
|
|
||||||
use data::tables::{self, BattleEventConfigID, HollowQuestID};
|
|
||||||
use proto::{
|
|
||||||
DungeonInfo, DungeonItemData, FightQuestInfo, LongFightInfo, LongFightSceneInfo, SceneInfo,
|
|
||||||
WeatherPoolInfo,
|
|
||||||
};
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::logic::{
|
|
||||||
battle::{
|
|
||||||
drop::FightDropPool,
|
|
||||||
unit::{AvatarUnit, BuddyUnit},
|
|
||||||
BuddyParam, DungeonQuestManager, LogicVariableTable, TeamDataItem,
|
|
||||||
},
|
|
||||||
BuddyTeamType, EHollowQuestType, ELocalPlayType, ESceneType, TimePeriodType, WeatherType,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::NapGameMode;
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum LongFightGameError {
|
|
||||||
#[error("Tried to run quest of type {0:?} using LongFight logic")]
|
|
||||||
InvalidQuestType(EHollowQuestType),
|
|
||||||
#[error("Battle group not found, quest id: {0}")]
|
|
||||||
BattleGroupNotFound(u32),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LongFightGame {
|
|
||||||
pub quest_id: u32,
|
|
||||||
pub battle_event_id: BattleEventConfigID,
|
|
||||||
pub play_type: ELocalPlayType,
|
|
||||||
pub time_period: TimePeriodType,
|
|
||||||
pub weather: WeatherType,
|
|
||||||
pub start_timestamp: i64,
|
|
||||||
pub team_data: TeamDataItem,
|
|
||||||
pub variable_table: LogicVariableTable,
|
|
||||||
pub fight_drop_pool: FightDropPool,
|
|
||||||
pub quest_manager: DungeonQuestManager,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LongFightGame {
|
|
||||||
const RALLY_GUIDANCE_BUDDY_ID: u32 = 50001;
|
|
||||||
|
|
||||||
pub fn create_rally_game(
|
|
||||||
quest_id: HollowQuestID,
|
|
||||||
avatars: &[u32],
|
|
||||||
buddy_id: u32,
|
|
||||||
time_period: TimePeriodType,
|
|
||||||
weather: WeatherType,
|
|
||||||
) -> Result<Self, LongFightGameError> {
|
|
||||||
let template = quest_id.template();
|
|
||||||
let quest_type = EHollowQuestType::from(template.hollow_quest_type);
|
|
||||||
|
|
||||||
if quest_type != EHollowQuestType::RallyBattle {
|
|
||||||
return Err(LongFightGameError::InvalidQuestType(quest_type));
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(battle_group) = tables::battle_group_config_template_tb::iter()
|
|
||||||
.find(|tmpl| tmpl.quest_id == template.id.value())
|
|
||||||
else {
|
|
||||||
return Err(LongFightGameError::BattleGroupNotFound(template.id.value()));
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buddy_params = vec![BuddyParam(
|
|
||||||
Self::RALLY_GUIDANCE_BUDDY_ID,
|
|
||||||
BuddyTeamType::RallyGuidance,
|
|
||||||
)];
|
|
||||||
|
|
||||||
if buddy_id != 0 {
|
|
||||||
buddy_params.push(BuddyParam(buddy_id, BuddyTeamType::Fighting));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
quest_id: template.id.value(),
|
|
||||||
battle_event_id: battle_group.battle_event_id,
|
|
||||||
play_type: ELocalPlayType::RallyLongFight,
|
|
||||||
time_period,
|
|
||||||
weather,
|
|
||||||
start_timestamp: util::cur_timestamp() as i64,
|
|
||||||
team_data: TeamDataItem::new(avatars, &buddy_params),
|
|
||||||
variable_table: LogicVariableTable::new(battle_group.battle_event_id),
|
|
||||||
fight_drop_pool: FightDropPool::new(battle_group.battle_event_id),
|
|
||||||
quest_manager: DungeonQuestManager::new_for_battle_group(battle_group.id),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NapGameMode for LongFightGame {
|
|
||||||
fn scene_type(&self) -> ESceneType {
|
|
||||||
ESceneType::LongFight
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scene_info(&self) -> Option<SceneInfo> {
|
|
||||||
Some(SceneInfo {
|
|
||||||
scene_type: self.scene_type() as u32,
|
|
||||||
battle_event_id: self.battle_event_id.value(),
|
|
||||||
play_type: self.play_type as u32,
|
|
||||||
long_fight_scene_info: Some(LongFightSceneInfo {
|
|
||||||
fight_data: Some(LongFightInfo {
|
|
||||||
fight_quest_info: Some(FightQuestInfo {
|
|
||||||
fight_variable_map: self.variable_table.to_client(),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
fight_drop_info: Some(self.fight_drop_pool.to_client()),
|
|
||||||
weather_pool: Some(WeatherPoolInfo {
|
|
||||||
time_period: self.time_period.to_string(),
|
|
||||||
weather: self.weather.to_string(),
|
|
||||||
febgjinpcbp: true,
|
|
||||||
bejeblcfcha: true,
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dungeon_info(&self) -> Option<DungeonInfo> {
|
|
||||||
Some(DungeonInfo {
|
|
||||||
quest_id: self.quest_id,
|
|
||||||
start_timestamp: self.start_timestamp,
|
|
||||||
dungeon_item_data: Some(DungeonItemData::default()),
|
|
||||||
avatar_list: self
|
|
||||||
.team_data
|
|
||||||
.avatar_member_list
|
|
||||||
.iter()
|
|
||||||
.map(AvatarUnit::to_client)
|
|
||||||
.collect(),
|
|
||||||
buddy_list: self
|
|
||||||
.team_data
|
|
||||||
.equipped_buddy_list
|
|
||||||
.iter()
|
|
||||||
.map(BuddyUnit::to_client)
|
|
||||||
.collect(),
|
|
||||||
dungeon_quest_info: Some(self.quest_manager.to_client()),
|
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +1,20 @@
|
||||||
mod fresh;
|
mod fresh;
|
||||||
mod frontend;
|
mod frontend;
|
||||||
mod hollow;
|
mod hollow;
|
||||||
mod long_fight;
|
|
||||||
pub use fresh::*;
|
pub use fresh::*;
|
||||||
pub use frontend::*;
|
pub use frontend::*;
|
||||||
pub use hollow::*;
|
pub use hollow::*;
|
||||||
pub use long_fight::*;
|
|
||||||
|
|
||||||
use proto::{DungeonInfo, SceneInfo, WorldInitScNotify};
|
use proto::{DungeonInfo, SceneInfo, WorldInitScNotify};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use super::{battle::DungeonQuestError, procedure::ProcedureError, ESceneType};
|
use super::{procedure::ProcedureError, ESceneType};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub enum GameInstance {
|
pub enum GameInstance {
|
||||||
Frontend(FrontendGame),
|
Frontend(FrontendGame),
|
||||||
Fresh(FreshGame),
|
Fresh(FreshGame),
|
||||||
Hollow(HollowGame),
|
Hollow(HollowGame),
|
||||||
LongFight(LongFightGame),
|
|
||||||
#[default]
|
#[default]
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
|
@ -32,10 +29,6 @@ pub enum LogicError {
|
||||||
Procedure(#[from] ProcedureError),
|
Procedure(#[from] ProcedureError),
|
||||||
#[error("hollow error: {0}")]
|
#[error("hollow error: {0}")]
|
||||||
Hollow(#[from] HollowGameError),
|
Hollow(#[from] HollowGameError),
|
||||||
#[error("longfight error: {0}")]
|
|
||||||
LongFight(#[from] LongFightGameError),
|
|
||||||
#[error("dungeon quest error: {0}")]
|
|
||||||
DungeonQuest(#[from] DungeonQuestError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameInstance {
|
impl GameInstance {
|
||||||
|
@ -48,7 +41,6 @@ impl GameInstance {
|
||||||
Self::Frontend(game) => game,
|
Self::Frontend(game) => game,
|
||||||
Self::Fresh(game) => game,
|
Self::Fresh(game) => game,
|
||||||
Self::Hollow(game) => game,
|
Self::Hollow(game) => game,
|
||||||
Self::LongFight(game) => game,
|
|
||||||
Self::Null => return Err(LogicError::GameIsNull),
|
Self::Null => return Err(LogicError::GameIsNull),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use data::tables::{AvatarBaseID, PostGirlConfigID, ProcedureConfigID};
|
use data::tables::{AvatarBaseID, ProcedureConfigID};
|
||||||
use proto::{BasicDataModelBin, PlayerBasicInfo};
|
use proto::{BasicDataModelBin, PlayerBasicInfo};
|
||||||
|
|
||||||
pub struct BasicDataModel {
|
pub struct BasicDataModel {
|
||||||
|
@ -8,7 +8,6 @@ pub struct BasicDataModel {
|
||||||
pub nick_name: Option<String>,
|
pub nick_name: Option<String>,
|
||||||
pub frontend_avatar_id: Option<AvatarBaseID>,
|
pub frontend_avatar_id: Option<AvatarBaseID>,
|
||||||
pub beginner_procedure_id: Option<ProcedureConfigID>,
|
pub beginner_procedure_id: Option<ProcedureConfigID>,
|
||||||
pub selected_post_girl_id: Option<PostGirlConfigID>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BasicDataModel {
|
impl Default for BasicDataModel {
|
||||||
|
@ -20,7 +19,6 @@ impl Default for BasicDataModel {
|
||||||
nick_name: None,
|
nick_name: None,
|
||||||
frontend_avatar_id: None,
|
frontend_avatar_id: None,
|
||||||
beginner_procedure_id: Some(ProcedureConfigID::new_unchecked(1)),
|
beginner_procedure_id: Some(ProcedureConfigID::new_unchecked(1)),
|
||||||
selected_post_girl_id: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,10 +37,6 @@ impl BasicDataModel {
|
||||||
avatar_id,
|
avatar_id,
|
||||||
frontend_avatar_id: avatar_id,
|
frontend_avatar_id: avatar_id,
|
||||||
kbjleelonfe: self.profile_icon,
|
kbjleelonfe: self.profile_icon,
|
||||||
has_nickname: match &self.nick_name {
|
|
||||||
Some(_name) => 1,
|
|
||||||
None => 0,
|
|
||||||
},
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +54,6 @@ impl BasicDataModel {
|
||||||
1.. => ProcedureConfigID::new(bin.beginner_procedure_id as u32),
|
1.. => ProcedureConfigID::new(bin.beginner_procedure_id as u32),
|
||||||
_ => None,
|
_ => None,
|
||||||
},
|
},
|
||||||
selected_post_girl_id: PostGirlConfigID::new(bin.selected_post_girl_id),
|
|
||||||
nick_name: match bin.nick_name.is_empty() {
|
nick_name: match bin.nick_name.is_empty() {
|
||||||
true => None,
|
true => None,
|
||||||
false => Some(bin.nick_name),
|
false => Some(bin.nick_name),
|
||||||
|
@ -82,10 +75,6 @@ impl BasicDataModel {
|
||||||
.beginner_procedure_id
|
.beginner_procedure_id
|
||||||
.map(|i| i.value() as i32)
|
.map(|i| i.value() as i32)
|
||||||
.unwrap_or(-1),
|
.unwrap_or(-1),
|
||||||
selected_post_girl_id: match self.selected_post_girl_id {
|
|
||||||
Some(post_girl_id) => post_girl_id.value(),
|
|
||||||
None => 0
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use std::collections::{BTreeSet, HashMap};
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
use data::tables::{quick_access_template_tb, QuickFuncID, UnlockConfigID};
|
use data::tables::UnlockConfigID;
|
||||||
use proto::{LockModelBin, QuickAccessData, QuickAccessType, UnlockData};
|
use proto::{LockModelBin, UnlockData};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LockModel {
|
pub struct LockModel {
|
||||||
unlock_list: BTreeSet<UnlockConfigID>,
|
unlock_list: BTreeSet<UnlockConfigID>,
|
||||||
quick_access_list: HashMap<u32, QuickFuncID>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LockModel {
|
impl LockModel {
|
||||||
|
@ -17,11 +16,6 @@ impl LockModel {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(UnlockConfigID::new_unchecked)
|
.map(UnlockConfigID::new_unchecked)
|
||||||
.collect(),
|
.collect(),
|
||||||
quick_access_list: bin
|
|
||||||
.quick_access_list
|
|
||||||
.into_iter()
|
|
||||||
.map(|(k, v)| (k, QuickFuncID::new_unchecked(v)))
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,39 +27,10 @@ impl LockModel {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|i| i.value())
|
.map(|i| i.value())
|
||||||
.collect(),
|
.collect(),
|
||||||
quick_access_list: self
|
|
||||||
.quick_access_list
|
|
||||||
.iter()
|
|
||||||
.map(|(k, v)| (k.clone(), v.value()))
|
|
||||||
.collect(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn quick_access_to_client(&self) -> Vec<QuickAccessData> {
|
|
||||||
let mut quick_access_data_list: Vec<QuickAccessData> = vec![];
|
|
||||||
for quick_access in quick_access_template_tb::iter() {
|
|
||||||
quick_access_data_list.push(QuickAccessData {
|
|
||||||
r#type: QuickAccessType::Direct.into(),
|
|
||||||
quick_access_index: quick_access.quick_access_index,
|
|
||||||
btn_id: quick_access.quick_func_id.value(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
for quick_access_index in 1..8 {
|
|
||||||
let mut btn_id = 0;
|
|
||||||
if let Some(id) = self.quick_access_list.get(&quick_access_index) {
|
|
||||||
btn_id = id.value();
|
|
||||||
}
|
|
||||||
quick_access_data_list.push(QuickAccessData {
|
|
||||||
r#type: QuickAccessType::QuickMenu.into(),
|
|
||||||
quick_access_index,
|
|
||||||
btn_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
quick_access_data_list
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_client(&self) -> UnlockData {
|
pub fn to_client(&self) -> UnlockData {
|
||||||
|
|
||||||
UnlockData {
|
UnlockData {
|
||||||
unlock_id_list: self
|
unlock_id_list: self
|
||||||
.unlock_list
|
.unlock_list
|
||||||
|
@ -73,7 +38,6 @@ impl LockModel {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|i| i.value())
|
.map(|i| i.value())
|
||||||
.collect(),
|
.collect(),
|
||||||
quick_access_data_list: self.quick_access_to_client(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,28 +49,4 @@ impl LockModel {
|
||||||
pub fn is_unlock(&self, id: UnlockConfigID) -> bool {
|
pub fn is_unlock(&self, id: UnlockConfigID) -> bool {
|
||||||
self.unlock_list.contains(&id)
|
self.unlock_list.contains(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mod_quick_access(&mut self, index: u32, id: Option<QuickFuncID>) -> QuickAccessData {
|
|
||||||
let btn_id = match id {
|
|
||||||
Some(quick_access_id) => {
|
|
||||||
if self.quick_access_list.contains_key(&index) {
|
|
||||||
*self.quick_access_list.get_mut(&index).unwrap() = quick_access_id;
|
|
||||||
} else {
|
|
||||||
self.quick_access_list.insert(index, quick_access_id);
|
|
||||||
}
|
|
||||||
quick_access_id.value()
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
if self.quick_access_list.contains_key(&index) {
|
|
||||||
self.quick_access_list.remove(&index);
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
QuickAccessData {
|
|
||||||
r#type: QuickAccessType::QuickMenu.into(),
|
|
||||||
quick_access_index: index,
|
|
||||||
btn_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,16 +14,12 @@ pub struct BasicDataModelBin {
|
||||||
pub frontend_avatar_id: i32,
|
pub frontend_avatar_id: i32,
|
||||||
#[prost(int32, tag = "6")]
|
#[prost(int32, tag = "6")]
|
||||||
pub beginner_procedure_id: i32,
|
pub beginner_procedure_id: i32,
|
||||||
#[prost(uint32, tag = "7")]
|
|
||||||
pub selected_post_girl_id: u32,
|
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
pub struct LockModelBin {
|
pub struct LockModelBin {
|
||||||
#[prost(int32, repeated, tag = "1")]
|
#[prost(int32, repeated, tag = "1")]
|
||||||
pub unlock_list: ::prost::alloc::vec::Vec<i32>,
|
pub unlock_list: ::prost::alloc::vec::Vec<i32>,
|
||||||
#[prost(map = "uint32, uint32", tag = "2")]
|
|
||||||
pub quick_access_list: ::std::collections::HashMap<u32, u32>,
|
|
||||||
}
|
}
|
||||||
#[allow(clippy::derive_partial_eq_without_eq)]
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
|
Loading…
Reference in a new issue