Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
ziqian zhang
Grasscutter
Commits
797afd4c
Commit
797afd4c
authored
Jul 26, 2022
by
Melledy
Committed by
GitHub
Jul 26, 2022
Browse files
Merge pull request #1553 from akatatsu27/questing
Major quest framework improvements
parents
1c5c3633
8bdcfb89
Changes
63
Hide whitespace changes
Inline
Side-by-side
src/main/java/emu/grasscutter/data/GameData.java
View file @
797afd4c
...
...
@@ -32,7 +32,7 @@ public class GameData {
// ExcelConfigs
private
static
final
Int2ObjectMap
<
PlayerLevelData
>
playerLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarData
>
avatarDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarLevelData
>
avatarLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarSkillDepotData
>
avatarSkillDepotDataMap
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -42,7 +42,7 @@ public class GameData {
private
static
final
Int2ObjectMap
<
AvatarPromoteData
>
avatarPromoteDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarTalentData
>
avatarTalentDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ProudSkillData
>
proudSkillDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ItemData
>
itemDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquaryLevelData
>
reliquaryLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
ReliquaryAffixData
>
reliquaryAffixDataMap
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -59,11 +59,11 @@ public class GameData {
private
static
final
Int2ObjectMap
<
GadgetData
>
gadgetDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
MonsterCurveData
>
monsterCurveDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
MonsterDescribeData
>
monsterDescribeDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarFlycloakData
>
avatarFlycloakDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarCostumeData
>
avatarCostumeDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
AvatarCostumeData
>
avatarCostumeDataItemIdMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
SceneData
>
sceneDataMap
=
new
Int2ObjectLinkedOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
FetterData
>
fetterDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
CodexQuestData
>
codexQuestDataMap
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -78,7 +78,7 @@ public class GameData {
private
static
final
ArrayList
<
CodexReliquaryData
>
codexReliquaryArrayList
=
new
ArrayList
<>();
private
static
final
Int2ObjectMap
<
FetterCharacterCardData
>
fetterCharacterCardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
RewardData
>
rewardDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WorldAreaData
>
worldAreaDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
WorldLevelData
>
worldLevelDataMap
=
new
Int2ObjectOpenHashMap
<>();
private
static
final
Int2ObjectMap
<
DailyDungeonData
>
dailyDungeonDataMap
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -110,6 +110,8 @@ public class GameData {
@Getter
private
static
final
Int2ObjectMap
<
MusicGameBasicData
>
musicGameBasicDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
PersonalLineData
>
personalLineDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
ChapterData
>
chapterDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
TriggerExcelConfigData
>
triggerExcelConfigDataMap
=
new
Int2ObjectOpenHashMap
<>();
@Getter
private
static
final
Map
<
String
,
ScriptSceneData
>
scriptSceneDataMap
=
new
HashMap
<>();
@Getter
private
static
final
Int2ObjectMap
<
OpenStateData
>
openStateDataMap
=
new
Int2ObjectOpenHashMap
<>();
...
...
@@ -117,29 +119,33 @@ public class GameData {
private
static
Map
<
Integer
,
List
<
Integer
>>
fetters
=
new
HashMap
<>();
private
static
Map
<
Integer
,
List
<
ShopGoodsData
>>
shopGoods
=
new
HashMap
<>();
private
static
final
IntList
scenePointIdList
=
new
IntArrayList
();
@Getter
private
static
final
List
<
OpenStateData
>
openStateList
=
new
ArrayList
<>();
public
static
Int2ObjectMap
<?>
getMapByResourceDef
(
Class
<?>
resourceDefinition
)
{
Int2ObjectMap
<?>
map
=
null
;
try
{
Field
field
=
GameData
.
class
.
getDeclaredField
(
Utils
.
lowerCaseFirstChar
(
resourceDefinition
.
getSimpleName
())
+
"Map"
);
field
.
setAccessible
(
true
);
map
=
(
Int2ObjectMap
<?>)
field
.
get
(
null
);
field
.
setAccessible
(
false
);
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"Error fetching resource map for "
+
resourceDefinition
.
getSimpleName
(),
e
);
}
return
map
;
}
public
static
Int2ObjectMap
<
String
>
getAbilityHashes
()
{
return
abilityHashes
;
}
public
static
Map
<
String
,
AbilityEmbryoEntry
>
getAbilityEmbryoInfo
()
{
return
abilityEmbryos
;
}
...
...
@@ -155,7 +161,7 @@ public class GameData {
public
static
Map
<
String
,
ScenePointEntry
>
getScenePointEntries
()
{
return
scenePointEntries
;
}
// TODO optimize
public
static
ScenePointEntry
getScenePointEntryById
(
int
sceneId
,
int
pointId
)
{
return
getScenePointEntries
().
get
(
sceneId
+
"_"
+
pointId
);
...
...
@@ -172,15 +178,15 @@ public class GameData {
public
static
Int2ObjectMap
<
HomeworldDefaultSaveData
>
getHomeworldDefaultSaveData
()
{
return
homeworldDefaultSaveData
;
}
public
static
Int2ObjectMap
<
SceneNpcBornData
>
getSceneNpcBornData
()
{
return
npcBornData
;
}
public
static
Int2ObjectMap
<
AvatarData
>
getAvatarDataMap
()
{
return
avatarDataMap
;
}
public
static
Int2ObjectMap
<
ItemData
>
getItemDataMap
()
{
return
itemDataMap
;
}
...
...
@@ -188,7 +194,7 @@ public class GameData {
public
static
Int2ObjectMap
<
AvatarSkillDepotData
>
getAvatarSkillDepotDataMap
()
{
return
avatarSkillDepotDataMap
;
}
public
static
Int2ObjectMap
<
AvatarSkillData
>
getAvatarSkillDataMap
()
{
return
avatarSkillDataMap
;
}
...
...
@@ -212,11 +218,11 @@ public class GameData {
public
static
Int2ObjectMap
<
WeaponLevelData
>
getWeaponLevelDataMap
()
{
return
weaponLevelDataMap
;
}
public
static
Int2ObjectMap
<
ReliquaryAffixData
>
getReliquaryAffixDataMap
()
{
return
reliquaryAffixDataMap
;
}
public
static
Int2ObjectMap
<
ReliquaryMainPropData
>
getReliquaryMainPropDataMap
()
{
return
reliquaryMainPropDataMap
;
}
...
...
@@ -228,7 +234,7 @@ public class GameData {
public
static
Int2ObjectMap
<
WeaponCurveData
>
getWeaponCurveDataMap
()
{
return
weaponCurveDataMap
;
}
public
static
Int2ObjectMap
<
AvatarCurveData
>
getAvatarCurveDataMap
()
{
return
avatarCurveDataMap
;
}
...
...
@@ -237,11 +243,11 @@ public class GameData {
ReliquaryLevelData
levelData
=
reliquaryLevelDataMap
.
get
((
rankLevel
<<
8
)
+
level
);
return
levelData
!=
null
?
levelData
.
getExp
()
:
0
;
}
public
static
ReliquaryLevelData
getRelicLevelData
(
int
rankLevel
,
int
level
)
{
return
reliquaryLevelDataMap
.
get
((
rankLevel
<<
8
)
+
level
);
}
public
static
WeaponPromoteData
getWeaponPromoteData
(
int
promoteId
,
int
promoteLevel
)
{
return
weaponPromoteDataMap
.
get
((
promoteId
<<
8
)
+
promoteLevel
);
}
...
...
@@ -257,7 +263,7 @@ public class GameData {
return
0
;
}
}
public
static
AvatarPromoteData
getAvatarPromoteData
(
int
promoteId
,
int
promoteLevel
)
{
return
avatarPromoteDataMap
.
get
((
promoteId
<<
8
)
+
promoteLevel
);
}
...
...
@@ -271,7 +277,7 @@ public class GameData {
AvatarFetterLevelData
levelData
=
avatarFetterLevelDataMap
.
get
(
level
);
return
levelData
!=
null
?
levelData
.
getExp
()
:
0
;
}
public
static
Int2ObjectMap
<
ProudSkillData
>
getProudSkillDataMap
()
{
return
proudSkillDataMap
;
}
...
...
@@ -318,7 +324,7 @@ public class GameData {
public
static
Int2ObjectMap
<
AvatarCostumeData
>
getAvatarCostumeDataMap
()
{
return
avatarCostumeDataMap
;
}
public
static
Int2ObjectMap
<
AvatarCostumeData
>
getAvatarCostumeDataItemIdMap
()
{
return
avatarCostumeDataItemIdMap
;
}
...
...
@@ -359,7 +365,7 @@ public class GameData {
public
static
Int2ObjectMap
<
WorldAreaData
>
getWorldAreaDataMap
()
{
return
worldAreaDataMap
;
}
public
static
Int2ObjectMap
<
WorldLevelData
>
getWorldLevelDataMap
()
{
return
worldLevelDataMap
;
}
...
...
@@ -367,7 +373,7 @@ public class GameData {
public
static
Int2ObjectMap
<
DungeonData
>
getDungeonDataMap
()
{
return
dungeonDataMap
;
}
public
static
Int2ObjectMap
<
DailyDungeonData
>
getDailyDungeonDataMap
()
{
return
dailyDungeonDataMap
;
}
...
...
@@ -403,11 +409,11 @@ public class GameData {
public
static
Int2ObjectMap
<
TowerFloorData
>
getTowerFloorDataMap
(){
return
towerFloorDataMap
;
}
public
static
Int2ObjectMap
<
TowerLevelData
>
getTowerLevelDataMap
(){
return
towerLevelDataMap
;
}
public
static
Int2ObjectMap
<
TowerScheduleData
>
getTowerScheduleDataMap
(){
return
towerScheduleDataMap
;
}
...
...
@@ -419,19 +425,19 @@ public class GameData {
public
static
Int2ObjectMap
<
ForgeData
>
getForgeDataMap
()
{
return
forgeDataMap
;
}
public
static
Int2ObjectMap
<
HomeWorldLevelData
>
getHomeWorldLevelDataMap
()
{
return
homeWorldLevelDataMap
;
}
public
static
Int2ObjectMap
<
FurnitureMakeConfigData
>
getFurnitureMakeConfigDataMap
()
{
return
furnitureMakeConfigDataMap
;
}
public
static
Int2ObjectMap
<
GatherData
>
getGatherDataMap
()
{
return
gatherDataMap
;
}
public
static
Int2ObjectMap
<
InvestigationMonsterData
>
getInvestigationMonsterDataMap
()
{
return
investigationMonsterDataMap
;
}
...
...
src/main/java/emu/grasscutter/data/ResourceLoader.java
View file @
797afd4c
...
...
@@ -56,22 +56,23 @@ public class ResourceLoader {
public
static
void
loadAll
()
{
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.status.resources.loading"
));
// Load ability lists
loadAbilityEmbryos
();
loadOpenConfig
();
loadAbilityModifiers
();
// Load resources
loadResources
();
// Process into depots
GameDepot
.
load
();
// Load spawn data and quests
loadSpawnData
();
loadQuests
();
// Load scene points - must be done AFTER resources are loaded
loadScenePoints
();
// Load default home layout
loadHomeworldDefaultSaveData
();
loadNpcBornData
();
// Load ability lists
loadAbilityEmbryos
();
loadOpenConfig
();
loadAbilityModifiers
();
// Load resources
loadResources
();
// Process into depots
GameDepot
.
load
();
// Load spawn data and quests
loadSpawnData
();
loadQuests
();
loadScriptSceneData
();
// Load scene points - must be done AFTER resources are loaded
loadScenePoints
();
// Load default home layout
loadHomeworldDefaultSaveData
();
loadNpcBornData
();
Grasscutter
.
getLogger
().
info
(
translate
(
"messages.status.resources.finish"
));
}
...
...
@@ -432,10 +433,32 @@ public class ResourceLoader {
Grasscutter
.
getLogger
().
debug
(
"Loaded "
+
GameData
.
getMainQuestDataMap
().
size
()
+
" MainQuestDatas."
);
}
@SneakyThrows
private
static
void
loadHomeworldDefaultSaveData
()
{
var
folder
=
Files
.
list
(
Path
.
of
(
RESOURCE
(
"BinOutput/HomeworldDefaultSave"
))).
toList
();
var
pattern
=
Pattern
.
compile
(
"scene(.*)_home_config.json"
);
public
static
void
loadScriptSceneData
()
{
File
folder
=
new
File
(
RESOURCE
(
"ScriptSceneData/"
));
if
(!
folder
.
exists
())
{
return
;
}
for
(
File
file
:
folder
.
listFiles
())
{
ScriptSceneData
sceneData
;
try
(
FileReader
fileReader
=
new
FileReader
(
file
))
{
sceneData
=
Grasscutter
.
getGsonFactory
().
fromJson
(
fileReader
,
ScriptSceneData
.
class
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
continue
;
}
GameData
.
getScriptSceneDataMap
().
put
(
file
.
getName
(),
sceneData
);
}
Grasscutter
.
getLogger
().
debug
(
"Loaded "
+
GameData
.
getScriptSceneDataMap
().
size
()
+
" ScriptSceneDatas."
);
}
@SneakyThrows
private
static
void
loadHomeworldDefaultSaveData
(){
var
folder
=
Files
.
list
(
Path
.
of
(
RESOURCE
(
"BinOutput/HomeworldDefaultSave"
))).
toList
();
var
pattern
=
Pattern
.
compile
(
"scene(.*)_home_config.json"
);
for
(
var
file
:
folder
)
{
var
matcher
=
pattern
.
matcher
(
file
.
getFileName
().
toString
());
...
...
src/main/java/emu/grasscutter/data/binout/MainQuestData.java
View file @
797afd4c
package
emu.grasscutter.data.binout
;
import
dev.morphia.annotations.Entity
;
import
emu.grasscutter.game.quest.enums.QuestType
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.Objects
;
public
class
MainQuestData
{
private
int
id
;
private
int
ICLLDPJFIMA
;
private
int
series
;
private
QuestType
type
;
private
long
titleTextMapHash
;
private
int
[]
suggestTrackMainQuestList
;
private
int
[]
rewardIdList
;
private
SubQuestData
[]
subQuests
;
public
int
getId
()
{
return
id
;
}
private
List
<
TalkData
>
talks
;
private
long
[]
preloadLuaList
;
public
int
getId
()
{
return
id
;
}
public
int
getSeries
()
{
return
series
;
}
public
QuestType
getType
()
{
return
type
;
}
public
long
getTitleTextMapHash
()
{
return
titleTextMapHash
;
}
public
int
[]
getSuggestTrackMainQuestList
()
{
return
suggestTrackMainQuestList
;
}
...
...
@@ -37,14 +43,28 @@ public class MainQuestData {
public
int
[]
getRewardIdList
()
{
return
rewardIdList
;
}
public
SubQuestData
[]
getSubQuests
()
{
return
subQuests
;
}
public
List
<
TalkData
>
getTalks
()
{
return
talks
;
}
public
void
onLoad
()
{
this
.
talks
=
talks
.
stream
().
filter
(
Objects:
:
nonNull
).
toList
();
}
@Data
public
static
class
SubQuestData
{
private
int
subId
;
private
int
order
;
}
@Data
@Entity
public
static
class
TalkData
{
private
int
id
;
private
String
heroTalk
;
}
}
src/main/java/emu/grasscutter/data/binout/ScriptSceneData.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.data.binout
;
import
com.google.gson.annotations.SerializedName
;
import
emu.grasscutter.scripts.data.SceneGroup
;
import
emu.grasscutter.utils.Position
;
import
lombok.Data
;
import
java.util.List
;
import
java.util.Map
;
@Data
public
class
ScriptSceneData
{
Map
<
String
,
ScriptObject
>
scriptObjectList
;
@Data
public
static
class
ScriptObject
{
//private SceneGroup groups;
@SerializedName
(
"dummy_points"
)
private
Map
<
String
,
List
<
Float
>>
dummyPoints
;
}
}
src/main/java/emu/grasscutter/data/excels/QuestData.java
View file @
797afd4c
...
...
@@ -36,10 +36,14 @@ public class QuestData extends GameResource {
private
List
<
QuestExecParam
>
beginExec
;
private
List
<
QuestExecParam
>
finishExec
;
private
List
<
QuestExecParam
>
failExec
;
private
Guide
guide
;
//ResourceLoader not happy if you remove getId() ~~
public
int
getId
()
{
return
subId
;
}
//Added getSubId() for clarity
public
int
getSubId
()
{
return
subId
;}
public
int
getMainId
()
{
return
mainId
;
...
...
@@ -62,7 +66,7 @@ public class QuestData extends GameResource {
}
public
LogicType
getAcceptCondComb
()
{
return
acceptCondComb
;
return
acceptCondComb
==
null
?
LogicType
.
LOGIC_NONE
:
acceptCondComb
;
}
public
List
<
QuestCondition
>
getAcceptCond
()
{
...
...
@@ -70,7 +74,7 @@ public class QuestData extends GameResource {
}
public
LogicType
getFinishCondComb
()
{
return
finishCondComb
;
return
finishCondComb
==
null
?
LogicType
.
LOGIC_NONE
:
finishCondComb
;
}
public
List
<
QuestCondition
>
getFinishCond
()
{
...
...
@@ -78,7 +82,7 @@ public class QuestData extends GameResource {
}
public
LogicType
getFailCondComb
()
{
return
failCondComb
;
return
failCondComb
==
null
?
LogicType
.
LOGIC_NONE
:
failCondComb
;
}
public
List
<
QuestCondition
>
getFailCond
()
{
...
...
@@ -118,4 +122,11 @@ public class QuestData extends GameResource {
private
String
count
;
}
@Data
public
static
class
Guide
{
private
String
type
;
private
List
<
String
>
param
;
private
int
guideScene
;
}
}
src/main/java/emu/grasscutter/data/excels/TriggerExcelConfigData.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.data.excels
;
import
emu.grasscutter.data.GameResource
;
import
emu.grasscutter.data.ResourceType
;
import
lombok.Getter
;
@ResourceType
(
name
=
"TriggerExcelConfigData.json"
)
@Getter
public
class
TriggerExcelConfigData
extends
GameResource
{
@Getter
private
int
id
;
private
int
sceneId
;
private
int
groupId
;
private
String
triggerName
;
}
src/main/java/emu/grasscutter/game/entity/EntityRegion.java
View file @
797afd4c
...
...
@@ -15,6 +15,7 @@ import java.util.concurrent.ConcurrentHashMap;
public
class
EntityRegion
extends
GameEntity
{
private
final
Position
position
;
private
boolean
hasNewEntities
;
private
boolean
entityLeave
;
private
final
Set
<
Integer
>
entities
;
// Ids of entities inside this region
private
final
SceneRegion
metaRegion
;
...
...
@@ -45,10 +46,17 @@ public class EntityRegion extends GameEntity{
hasNewEntities
=
false
;
}
public
void
removeEntity
(
int
entityId
)
{
this
.
getEntities
().
remove
(
entityId
);
this
.
entityLeave
=
true
;
}
public
void
removeEntity
(
GameEntity
entity
)
{
this
.
getEntities
().
remove
(
entity
.
getId
());
this
.
entityLeave
=
true
;
}
public
boolean
entityLeave
()
{
return
this
.
entityLeave
;}
public
void
resetEntityLeave
()
{
this
.
entityLeave
=
false
;}
@Override
public
Int2FloatOpenHashMap
getFightProperties
()
{
return
null
;
...
...
src/main/java/emu/grasscutter/game/player/Player.java
View file @
797afd4c
...
...
@@ -14,12 +14,8 @@ import emu.grasscutter.game.activity.ActivityManager;
import
emu.grasscutter.game.avatar.Avatar
;
import
emu.grasscutter.game.avatar.AvatarStorage
;
import
emu.grasscutter.game.battlepass.BattlePassManager
;
import
emu.grasscutter.game.entity.EntityMonster
;
import
emu.grasscutter.game.entity.EntityVehicle
;
import
emu.grasscutter.game.entity.*
;
import
emu.grasscutter.game.home.GameHome
;
import
emu.grasscutter.game.entity.EntityGadget
;
import
emu.grasscutter.game.entity.EntityItem
;
import
emu.grasscutter.game.entity.GameEntity
;
import
emu.grasscutter.game.expedition.ExpeditionInfo
;
import
emu.grasscutter.game.friends.FriendsList
;
import
emu.grasscutter.game.friends.PlayerProfile
;
...
...
@@ -43,6 +39,7 @@ import emu.grasscutter.game.props.ClimateType;
import
emu.grasscutter.game.props.PlayerProperty
;
import
emu.grasscutter.game.props.WatcherTriggerType
;
import
emu.grasscutter.game.quest.QuestManager
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.shop.ShopLimit
;
import
emu.grasscutter.game.tower.TowerData
;
import
emu.grasscutter.game.tower.TowerManager
;
...
...
@@ -61,6 +58,7 @@ import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo
import
emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture
;
import
emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail
;
import
emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType
;
import
emu.grasscutter.scripts.data.SceneRegion
;
import
emu.grasscutter.server.event.player.PlayerJoinEvent
;
import
emu.grasscutter.server.event.player.PlayerQuitEvent
;
import
emu.grasscutter.server.game.GameServer
;
...
...
@@ -74,6 +72,7 @@ import emu.grasscutter.utils.Utils;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
lombok.Getter
;
import
lombok.Setter
;
import
static
emu
.
grasscutter
.
config
.
Configuration
.*;
...
...
@@ -122,6 +121,7 @@ public class Player {
@Getter
private
Map
<
Long
,
ExpeditionInfo
>
expeditionInfo
;
@Getter
private
Map
<
Integer
,
Integer
>
unlockedRecipies
;
@Getter
private
List
<
ActiveForgeData
>
activeForges
;
@Getter
private
Map
<
Integer
,
Integer
>
questGlobalVariables
;
@Transient
private
long
nextGuid
=
0
;
@Transient
private
int
peerId
;
...
...
@@ -151,7 +151,7 @@ public class Player {
@Getter
private
transient
CookingManager
cookingManager
;
@Getter
private
transient
ActivityManager
activityManager
;
@Getter
private
transient
PlayerBuffManager
buffManager
;
// Manager data (Save-able to the database)
private
PlayerProfile
playerProfile
;
private
TeamManager
teamManager
;
...
...
@@ -579,9 +579,38 @@ public class Player {
return
towerData
;
}
public
PlayerGachaInfo
getGachaInfo
()
{
return
gachaInfo
;
public
void
setQuestManager
(
QuestManager
questManager
)
{
this
.
questManager
=
questManager
;
}
public
void
onEnterRegion
(
SceneRegion
region
)
{
getQuestManager
().
forEachActiveQuest
(
quest
->
{
if
(
quest
.
getTriggers
().
containsKey
(
"ENTER_REGION_"
+
String
.
valueOf
(
region
.
config_id
)))
{
// If trigger hasn't been fired yet
if
(!
Boolean
.
TRUE
.
equals
(
quest
.
getTriggers
().
put
(
"ENTER_REGION_"
+
String
.
valueOf
(
region
.
config_id
),
true
)))
{
//getSession().send(new PacketServerCondMeetQuestListUpdateNotify());
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_TRIGGER_FIRE
,
quest
.
getTriggerData
().
get
(
"ENTER_REGION_"
+
String
.
valueOf
(
region
.
config_id
)).
getId
(),
0
);
}
}
});
}
public
void
onLeaveRegion
(
SceneRegion
region
)
{
getQuestManager
().
forEachActiveQuest
(
quest
->
{
if
(
quest
.
getTriggers
().
containsKey
(
"LEAVE_REGION_"
+
String
.
valueOf
(
region
.
config_id
)))
{
// If trigger hasn't been fired yet
if
(!
Boolean
.
TRUE
.
equals
(
quest
.
getTriggers
().
put
(
"LEAVE_REGION_"
+
String
.
valueOf
(
region
.
config_id
),
true
)))
{
getSession
().
send
(
new
PacketServerCondMeetQuestListUpdateNotify
());
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_TRIGGER_FIRE
,
quest
.
getTriggerData
().
get
(
"LEAVE_REGION_"
+
String
.
valueOf
(
region
.
config_id
)).
getId
(),
0
);
}
}
});
}
public
PlayerGachaInfo
getGachaInfo
()
{
return
gachaInfo
;
}
public
PlayerProfile
getProfile
()
{
if
(
this
.
playerProfile
==
null
)
{
...
...
@@ -892,7 +921,7 @@ public class Player {
public
boolean
hasSentLoginPackets
()
{
return
hasSentLoginPackets
;
}
public
void
addAvatar
(
Avatar
avatar
,
boolean
addToCurrentTeam
)
{
boolean
result
=
getAvatars
().
addAvatar
(
avatar
);
...
...
@@ -1327,6 +1356,11 @@ public class Player {
// Execute daily reset logic if this is a new day.
this
.
doDailyReset
();
// Rewind active quests, and put the player to a rewind position it finds (if any) of an active quest
getQuestManager
().
onLogin
();
// Packets
session
.
send
(
new
PacketPlayerDataNotify
(
this
));
// Player data
session
.
send
(
new
PacketStoreWeightLimitNotify
());
...
...
src/main/java/emu/grasscutter/game/quest/GameMainQuest.java
View file @
797afd4c
...
...
@@ -2,7 +2,15 @@ package emu.grasscutter.game.quest;
import
java.util.*
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.binout.ScriptSceneData
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.quest.enums.LogicType
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.scripts.ScriptLoader
;
import
emu.grasscutter.server.packet.send.PacketCodexDataUpdateNotify
;
import
emu.grasscutter.utils.Position
;
import
lombok.Getter
;
import
org.bson.types.ObjectId
;
import
dev.morphia.annotations.Entity
;
...
...
@@ -11,6 +19,7 @@ import dev.morphia.annotations.Indexed;
import
dev.morphia.annotations.Transient
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.binout.MainQuestData
;
import
emu.grasscutter.data.binout.MainQuestData.*
;
import
emu.grasscutter.data.excels.RewardData
;
import
emu.grasscutter.database.DatabaseHelper
;
import
emu.grasscutter.game.player.Player
;
...
...
@@ -23,24 +32,33 @@ import emu.grasscutter.net.proto.QuestOuterClass.Quest;
import
emu.grasscutter.server.packet.send.PacketFinishedParentQuestUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify
;
import
emu.grasscutter.utils.Utils
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
javax.script.Bindings
;
import
javax.script.CompiledScript
;
import
javax.script.ScriptException
;
import
static
emu
.
grasscutter
.
config
.
Configuration
.
SCRIPT
;
@Entity
(
value
=
"quests"
,
useDiscriminator
=
false
)
public
class
GameMainQuest
{
@Id
private
ObjectId
id
;
@Indexed
private
int
ownerUid
;
@Transient
private
Player
owner
;
private
Map
<
Integer
,
GameQuest
>
childQuests
;
private
int
parentQuestId
;
private
int
[]
questVars
;
private
ParentQuestState
state
;
private
boolean
isFinished
;
List
<
QuestGroupSuite
>
questGroupSuites
;
@Indexed
@Getter
private
int
ownerUid
;
@Transient
@Getter
private
Player
owner
;
@Transient
@Getter
private
QuestManager
questManager
;
@Getter
private
Map
<
Integer
,
GameQuest
>
childQuests
;
@Getter
private
int
parentQuestId
;
@Getter
private
int
[]
questVars
;
//QuestUpdateQuestVarReq is sent in two stages...
@Getter
private
List
<
Integer
>
questVarsUpdate
;
@Getter
private
ParentQuestState
state
;
@Getter
private
boolean
isFinished
;
@Getter
List
<
QuestGroupSuite
>
questGroupSuites
;
@Getter
int
[]
suggestTrackMainQuestList
;
@Getter
private
Map
<
Integer
,
TalkData
>
talks
;
//key is subId
private
Map
<
Integer
,
Position
>
rewindPositions
;
private
Map
<
Integer
,
Position
>
rewindRotations
;
@Deprecated
// Morphia only. Do not use.
public
GameMainQuest
()
{}
...
...
@@ -48,52 +66,60 @@ public class GameMainQuest {
public
GameMainQuest
(
Player
player
,
int
parentQuestId
)
{
this
.
owner
=
player
;
this
.
ownerUid
=
player
.
getUid
();
this
.
questManager
=
player
.
getQuestManager
();
this
.
parentQuestId
=
parentQuestId
;
this
.
childQuests
=
new
HashMap
<>();
this
.
questVars
=
new
int
[
5
];
this
.
talks
=
new
HashMap
<>();
//official server always has a list of 5 questVars, with default value 0
this
.
questVars
=
new
int
[]
{
0
,
0
,
0
,
0
,
0
};
this
.
state
=
ParentQuestState
.
PARENT_QUEST_STATE_NONE
;
this
.
questGroupSuites
=
new
ArrayList
<>();
this
.
rewindPositions
=
new
HashMap
<>();
this
.
rewindRotations
=
new
HashMap
<>();
addAllChildQuests
();
addRewindPoints
();
}
public
int
getParentQuestId
()
{
return
parentQuestId
;
}
public
int
getOwnerUid
()
{
return
ownerUid
;
}
public
Player
getOwner
()
{
return
owner
;
}
private
void
addAllChildQuests
()
{
List
<
Integer
>
subQuestIds
=
Arrays
.
stream
(
GameData
.
getMainQuestDataMap
().
get
(
this
.
parentQuestId
).
getSubQuests
()).
map
(
SubQuestData:
:
getSubId
).
toList
();
for
(
Integer
subQuestId
:
subQuestIds
)
{
QuestData
questConfig
=
GameData
.
getQuestDataMap
().
get
(
subQuestId
);
this
.
childQuests
.
put
(
subQuestId
,
new
GameQuest
(
this
,
questConfig
));
}
}
public
void
setOwner
(
Player
player
)
{
if
(
player
.
getUid
()
!=
this
.
getOwnerUid
())
return
;
this
.
owner
=
player
;
}
public
Map
<
Integer
,
GameQuest
>
getChildQuests
()
{
return
childQuests
;
}
public
int
getQuestVar
(
int
i
)
{
return
questVars
[
i
];
}
public
void
setQuestVar
(
int
i
,
int
value
)
{
int
previousValue
=
this
.
questVars
[
i
];
this
.
questVars
[
i
]
=
value
;
Grasscutter
.
getLogger
().
debug
(
"questVar {} value changed from {} to {}"
,
i
,
previousValue
,
value
);
}
public
GameQuest
getChildQuestById
(
int
id
)
{
return
this
.
getChildQuests
().
get
(
id
);
}
public
void
incQuestVar
(
int
i
,
int
inc
)
{
int
previousValue
=
this
.
questVars
[
i
];
this
.
questVars
[
i
]
+=
inc
;
Grasscutter
.
getLogger
().
debug
(
"questVar {} value incremented from {} to {}"
,
i
,
previousValue
,
previousValue
+
inc
);
}
public
int
[]
getQuestVars
()
{
return
questVars
;
}
public
void
decQuestVar
(
int
i
,
int
dec
)
{
int
previousValue
=
this
.
questVars
[
i
];
this
.
questVars
[
i
]
-=
dec
;
Grasscutter
.
getLogger
().
debug
(
"questVar {} value decremented from {} to {}"
,
i
,
previousValue
,
previousValue
-
dec
);
}
public
ParentQuestState
getState
()
{
return
state
;
}
public
boolean
isFinished
(
)
{
return
isFinished
;
public
GameQuest
getChildQuestById
(
int
id
)
{
return
this
.
getChildQuests
().
get
(
id
)
;
}
public
List
<
QuestGroupSuite
>
getQuestGroupSuites
()
{
return
questGroupSuites
;
public
GameQuest
getChildQuestByOrder
(
int
order
)
{
return
this
.
getChildQuests
().
values
().
stream
().
filter
(
p
->
p
.
getQuestData
().
getOrder
()
==
order
).
toList
().
get
(
0
);
}
public
void
finish
()
{
...
...
@@ -120,9 +146,193 @@ public class GameMainQuest {
// handoff main quest
if
(
mainQuestData
.
getSuggestTrackMainQuestList
()
!=
null
){
Arrays
.
stream
(
mainQuestData
.
getSuggestTrackMainQuestList
())
.
forEach
(
getOwner
().
getQuestManager
()::
startMainQuest
);
.
forEach
(
getQuestManager
()::
startMainQuest
);
}
}
//TODO
public
void
fail
()
{}
public
void
cancel
()
{}
// Rewinds to the last finished/unfinished rewind quest, and returns the avatar rewind position (if it exists)
public
List
<
Position
>
rewind
()
{
if
(
this
.
questManager
==
null
)
{
this
.
questManager
=
getOwner
().
getQuestManager
();
}
List
<
GameQuest
>
sortedByOrder
=
new
ArrayList
<>(
getChildQuests
().
values
().
stream
().
filter
(
q
->
q
.
getQuestData
().
isRewind
()).
toList
());
sortedByOrder
.
sort
((
a
,
b
)
->
{
if
(
a
==
b
){
return
0
;
}
return
a
.
getQuestData
().
getOrder
()
>
b
.
getQuestData
().
getOrder
()
?
1
:
-
1
;});
boolean
didRewind
=
false
;
for
(
GameQuest
quest
:
sortedByOrder
)
{
int
i
=
sortedByOrder
.
indexOf
(
quest
);
if
(
i
==
sortedByOrder
.
size
())
{
didRewind
=
quest
.
rewind
(
null
);
}
else
{
didRewind
=
quest
.
rewind
(
sortedByOrder
.
get
(
i
+
1
));
}
if
(
didRewind
)
{
break
;
}
}
List
<
GameQuest
>
rewindQuests
=
getChildQuests
().
values
().
stream
()
.
filter
(
p
->
(
p
.
getState
()
==
QuestState
.
QUEST_STATE_UNFINISHED
||
p
.
getState
()
==
QuestState
.
QUEST_STATE_FINISHED
)
&&
p
.
getQuestData
().
isRewind
()).
toList
();
for
(
GameQuest
quest
:
rewindQuests
)
{
if
(
rewindPositions
.
containsKey
(
quest
.
getSubQuestId
()))
{
List
<
Position
>
posAndRot
=
new
ArrayList
<>();
posAndRot
.
add
(
0
,
rewindPositions
.
get
(
quest
.
getSubQuestId
()));
posAndRot
.
add
(
1
,
rewindRotations
.
get
(
quest
.
getSubQuestId
()));
return
posAndRot
;
}
}
return
null
;
}
public
void
addRewindPoints
()
{
Bindings
bindings
=
ScriptLoader
.
getEngine
().
createBindings
();
CompiledScript
cs
=
ScriptLoader
.
getScriptByPath
(
SCRIPT
(
"Quest/Share/Q"
+
getParentQuestId
()
+
"ShareConfig."
+
ScriptLoader
.
getScriptType
()));
if
(
cs
==
null
)
{
Grasscutter
.
getLogger
().
error
(
"Couldn't find Q"
+
getParentQuestId
()
+
"ShareConfig."
+
ScriptLoader
.
getScriptType
());
return
;
}
// Eval script
try
{
cs
.
eval
(
bindings
);
var
rewindDataMap
=
ScriptLoader
.
getSerializer
().
toMap
(
RewindData
.
class
,
bindings
.
get
(
"rewind_data"
));
for
(
String
subId
:
rewindDataMap
.
keySet
())
{
RewindData
questRewind
=
rewindDataMap
.
get
(
subId
);
if
(
questRewind
!=
null
)
{
RewindData
.
AvatarData
avatarData
=
questRewind
.
getAvatar
();
if
(
avatarData
!=
null
)
{
String
avatarPos
=
avatarData
.
getPos
();
QuestData
.
Guide
guide
=
GameData
.
getQuestDataMap
().
get
(
Integer
.
valueOf
(
subId
)).
getGuide
();
if
(
guide
!=
null
)
{
int
sceneId
=
guide
.
getGuideScene
();
ScriptSceneData
fullGlobals
=
GameData
.
getScriptSceneDataMap
().
get
(
"flat.luas.scenes.full_globals.lua.json"
);
if
(
fullGlobals
!=
null
)
{
ScriptSceneData
.
ScriptObject
dummyPointScript
=
fullGlobals
.
getScriptObjectList
().
get
(
sceneId
+
"/scene"
+
sceneId
+
"_dummy_points.lua"
);
if
(
dummyPointScript
!=
null
)
{
Map
<
String
,
List
<
Float
>>
dummyPointMap
=
dummyPointScript
.
getDummyPoints
();
if
(
dummyPointMap
!=
null
)
{
List
<
Float
>
avatarPosPos
=
dummyPointMap
.
get
(
avatarPos
+
".pos"
);
if
(
avatarPosPos
!=
null
)
{
Position
pos
=
new
Position
(
avatarPosPos
.
get
(
0
),
avatarPosPos
.
get
(
1
),
avatarPosPos
.
get
(
2
));
List
<
Float
>
avatarPosRot
=
dummyPointMap
.
get
(
avatarPos
+
".rot"
);
Position
rot
=
new
Position
(
avatarPosRot
.
get
(
0
),
avatarPosRot
.
get
(
1
),
avatarPosRot
.
get
(
2
));
rewindPositions
.
put
(
Integer
.
valueOf
(
subId
),
pos
);
rewindRotations
.
put
(
Integer
.
valueOf
(
subId
),
rot
);
Grasscutter
.
getLogger
().
debug
(
"Succesfully loaded rewind position for subQuest {}"
,
subId
);
}
}
}
}
}
}
}
}
}
catch
(
ScriptException
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred while loading rewind positions"
);
}
}
public
void
tryAcceptSubQuests
(
QuestTrigger
condType
,
String
paramStr
,
int
...
params
)
{
try
{
List
<
GameQuest
>
subQuestsWithCond
=
getChildQuests
().
values
().
stream
()
.
filter
(
p
->
p
.
getState
()
==
QuestState
.
QUEST_STATE_UNSTARTED
)
.
filter
(
p
->
p
.
getQuestData
().
getAcceptCond
().
stream
().
anyMatch
(
q
->
q
.
getType
()
==
condType
))
.
toList
();
for
(
GameQuest
subQuestWithCond
:
subQuestsWithCond
)
{
List
<
QuestData
.
QuestCondition
>
acceptCond
=
subQuestWithCond
.
getQuestData
().
getAcceptCond
();
int
[]
accept
=
new
int
[
acceptCond
.
size
()];
for
(
int
i
=
0
;
i
<
subQuestWithCond
.
getQuestData
().
getAcceptCond
().
size
();
i
++)
{
QuestData
.
QuestCondition
condition
=
acceptCond
.
get
(
i
);
boolean
result
=
this
.
getOwner
().
getServer
().
getQuestSystem
().
triggerCondition
(
subQuestWithCond
,
condition
,
paramStr
,
params
);
accept
[
i
]
=
result
?
1
:
0
;
}
boolean
shouldAccept
=
LogicType
.
calculate
(
subQuestWithCond
.
getQuestData
().
getAcceptCondComb
(),
accept
);
if
(
shouldAccept
)
{
subQuestWithCond
.
start
();
getQuestManager
().
getAddToQuestListUpdateNotify
().
add
(
subQuestWithCond
);
}
}
this
.
save
();
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred while trying to accept quest."
,
e
);
}
}
public
void
tryFailSubQuests
(
QuestTrigger
condType
,
String
paramStr
,
int
...
params
)
{
try
{
List
<
GameQuest
>
subQuestsWithCond
=
getChildQuests
().
values
().
stream
()
.
filter
(
p
->
p
.
getState
()
==
QuestState
.
QUEST_STATE_UNFINISHED
)
.
filter
(
p
->
p
.
getQuestData
().
getFailCond
().
stream
().
anyMatch
(
q
->
q
.
getType
()
==
condType
))
.
toList
();
for
(
GameQuest
subQuestWithCond
:
subQuestsWithCond
)
{
List
<
QuestData
.
QuestCondition
>
failCond
=
subQuestWithCond
.
getQuestData
().
getFailCond
();
int
[]
fail
=
new
int
[
failCond
.
size
()];
for
(
int
i
=
0
;
i
<
subQuestWithCond
.
getQuestData
().
getFailCond
().
size
();
i
++)
{
QuestData
.
QuestCondition
condition
=
failCond
.
get
(
i
);
boolean
result
=
this
.
getOwner
().
getServer
().
getQuestSystem
().
triggerContent
(
subQuestWithCond
,
condition
,
paramStr
,
params
);
fail
[
i
]
=
result
?
1
:
0
;
}
boolean
shouldFail
=
LogicType
.
calculate
(
subQuestWithCond
.
getQuestData
().
getFailCondComb
(),
fail
);
if
(
shouldFail
)
{
subQuestWithCond
.
fail
();
getQuestManager
().
getAddToQuestListUpdateNotify
().
add
(
subQuestWithCond
);
}
}
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred while trying to fail quest."
,
e
);
}
}
public
void
tryFinishSubQuests
(
QuestTrigger
condType
,
String
paramStr
,
int
...
params
)
{
try
{
List
<
GameQuest
>
subQuestsWithCond
=
getChildQuests
().
values
().
stream
()
//There are subQuests with no acceptCond, but can be finished (example: 35104)
.
filter
(
p
->
p
.
getState
()
==
QuestState
.
QUEST_STATE_UNFINISHED
&&
p
.
getQuestData
().
getAcceptCond
()
!=
null
)
.
filter
(
p
->
p
.
getQuestData
().
getFinishCond
().
stream
().
anyMatch
(
q
->
q
.
getType
()
==
condType
))
.
toList
();
for
(
GameQuest
subQuestWithCond
:
subQuestsWithCond
)
{
List
<
QuestData
.
QuestCondition
>
finishCond
=
subQuestWithCond
.
getQuestData
().
getFinishCond
();
int
[]
finish
=
new
int
[
finishCond
.
size
()];
for
(
int
i
=
0
;
i
<
subQuestWithCond
.
getQuestData
().
getFinishCond
().
size
();
i
++)
{
QuestData
.
QuestCondition
condition
=
finishCond
.
get
(
i
);
boolean
result
=
this
.
getOwner
().
getServer
().
getQuestSystem
().
triggerContent
(
subQuestWithCond
,
condition
,
paramStr
,
params
);
finish
[
i
]
=
result
?
1
:
0
;
}
boolean
shouldFinish
=
LogicType
.
calculate
(
subQuestWithCond
.
getQuestData
().
getFinishCondComb
(),
finish
);
if
(
shouldFinish
)
{
subQuestWithCond
.
finish
();
getQuestManager
().
getAddToQuestListUpdateNotify
().
add
(
subQuestWithCond
);
}
}
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
debug
(
"An error occurred while trying to finish quest."
,
e
);
}
}
public
void
save
()
{
DatabaseHelper
.
saveQuest
(
this
);
...
...
@@ -131,25 +341,28 @@ public class GameMainQuest {
public
ParentQuest
toProto
()
{
ParentQuest
.
Builder
proto
=
ParentQuest
.
newBuilder
()
.
setParentQuestId
(
getParentQuestId
())
.
setIsFinished
(
isFinished
())
.
setParentQuestState
(
getState
().
getValue
())
.
setCutsceneEncryptionKey
(
QuestManager
.
getQuestKey
(
parentQuestId
));
.
setIsFinished
(
isFinished
());
for
(
GameQuest
quest
:
this
.
getChildQuests
().
values
())
{
ChildQuest
childQuest
=
ChildQuest
.
newBuilder
()
.
setQuestId
(
quest
.
getQuestId
())
.
setState
(
quest
.
getState
().
getValue
())
.
build
();
proto
.
addChildQuestList
(
childQuest
);
}
proto
.
setParentQuestState
(
getState
().
getValue
())
.
setCutsceneEncryptionKey
(
QuestManager
.
getQuestKey
(
parentQuestId
));
for
(
GameQuest
quest
:
this
.
getChildQuests
().
values
())
{
if
(
quest
.
getState
()
!=
QuestState
.
QUEST_STATE_UNSTARTED
)
{
ChildQuest
childQuest
=
ChildQuest
.
newBuilder
()
.
setQuestId
(
quest
.
getSubQuestId
())
.
setState
(
quest
.
getState
().
getValue
())
.
build
();
proto
.
addChildQuestList
(
childQuest
);
}
}
for
(
int
i
:
getQuestVars
())
{
proto
.
addQuestVar
(
i
);
}
if
(
getQuestVars
()
!=
null
)
{
for
(
int
i
:
getQuestVars
())
{
proto
.
addQuestVar
(
i
);
}
}
return
proto
.
build
();
}
}
src/main/java/emu/grasscutter/game/quest/GameQuest.java
View file @
797afd4c
...
...
@@ -4,51 +4,84 @@ import dev.morphia.annotations.Entity;
import
dev.morphia.annotations.Transient
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.binout.MainQuestData
;
import
emu.grasscutter.data.binout.MainQuestData.SubQuestData
;
import
emu.grasscutter.data.excels.ChapterData
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.data.excels.
QuestData.QuestCondition
;
import
emu.grasscutter.data.excels.
TriggerExcelConfigData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.quest.enums.LogicType
;
import
emu.grasscutter.game.quest.enums.QuestState
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.net.proto.ChapterStateOuterClass
;
import
emu.grasscutter.net.proto.QuestOuterClass.Quest
;
import
emu.grasscutter.scripts.data.SceneGroup
;
import
emu.grasscutter.server.packet.send.PacketChapterStateNotify
;
import
emu.grasscutter.server.packet.send.PacketQuestListUpdateNotify
;
import
emu.grasscutter.server.packet.send.PacketQuestProgressUpdateNotify
;
import
emu.grasscutter.utils.Utils
;
import
lombok.Getter
;
import
lombok.Setter
;
import
javax.script.Bindings
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
@Entity
public
class
GameQuest
{
@Transient
private
GameMainQuest
mainQuest
;
@Transient
private
QuestData
questData
;
@Transient
@Getter
@Setter
private
GameMainQuest
mainQuest
;
@Transient
@Getter
private
QuestData
questData
;
private
int
questId
;
private
int
mainQuestId
;
@Getter
private
int
subQuestId
;
@Getter
private
int
mainQuestId
;
@Getter
@Setter
private
QuestState
state
;
private
int
startTime
;
private
int
acceptTime
;
private
int
finishTime
;
@Getter
@Setter
private
int
startTime
;
@Getter
@Setter
private
int
acceptTime
;
@Getter
@Setter
private
int
finishTime
;
private
int
[]
finishProgressList
;
private
int
[]
failProgressList
;
@Getter
private
int
[]
finishProgressList
;
@Getter
private
int
[]
failProgressList
;
@Transient
@Getter
private
Map
<
String
,
TriggerExcelConfigData
>
triggerData
;
@Getter
private
Map
<
String
,
Boolean
>
triggers
;
private
transient
Bindings
bindings
;
@Deprecated
// Morphia only. Do not use.
public
GameQuest
()
{}
@Deprecated
// Morphia only. Do not use.
public
GameQuest
()
{}
public
GameQuest
(
GameMainQuest
mainQuest
,
QuestData
questData
)
{
this
.
mainQuest
=
mainQuest
;
this
.
questId
=
questData
.
getId
();
this
.
mainQuestId
=
questData
.
getMainId
();
this
.
questData
=
questData
;
public
GameQuest
(
GameMainQuest
mainQuest
,
QuestData
questData
)
{
this
.
mainQuest
=
mainQuest
;
this
.
subQuestId
=
questData
.
getId
();
this
.
mainQuestId
=
questData
.
getMainId
();
this
.
questData
=
questData
;
this
.
state
=
QuestState
.
QUEST_STATE_UNSTARTED
;
this
.
triggerData
=
new
HashMap
<>();
this
.
triggers
=
new
HashMap
<>();
}
public
void
start
()
{
this
.
acceptTime
=
Utils
.
getCurrentSeconds
();
this
.
startTime
=
this
.
acceptTime
;
this
.
state
=
QuestState
.
QUEST_STATE_UNFINISHED
;
List
<
QuestData
.
QuestCondition
>
triggerCond
=
questData
.
getFinishCond
().
stream
()
.
filter
(
p
->
p
.
getType
()
==
QuestTrigger
.
QUEST_CONTENT_TRIGGER_FIRE
).
toList
();
if
(
triggerCond
.
size
()
>
0
)
{
for
(
QuestData
.
QuestCondition
cond
:
triggerCond
)
{
TriggerExcelConfigData
newTrigger
=
GameData
.
getTriggerExcelConfigDataMap
().
get
(
cond
.
getParam
()[
0
]);
if
(
newTrigger
!=
null
)
{
if
(
this
.
triggerData
==
null
)
{
this
.
triggerData
=
new
HashMap
<>();
}
triggerData
.
put
(
newTrigger
.
getTriggerName
(),
newTrigger
);
triggers
.
put
(
newTrigger
.
getTriggerName
(),
false
);
SceneGroup
group
=
SceneGroup
.
of
(
newTrigger
.
getGroupId
()).
load
(
newTrigger
.
getSceneId
());
getOwner
().
getWorld
().
getSceneById
(
newTrigger
.
getSceneId
()).
loadTriggerFromGroup
(
group
,
newTrigger
.
getTriggerName
());
}
}
}
if
(
questData
.
getFinishCond
()
!=
null
&&
questData
.
get
Accept
Cond
().
size
()
!=
0
)
{
if
(
questData
.
getFinishCond
()
!=
null
&&
questData
.
get
Finish
Cond
().
size
()
!=
0
)
{
this
.
finishProgressList
=
new
int
[
questData
.
getFinishCond
().
size
()];
}
...
...
@@ -56,201 +89,136 @@ public class GameQuest {
this
.
failProgressList
=
new
int
[
questData
.
getFailCond
().
size
()];
}
this
.
mainQuest
.
getChildQuests
().
put
(
this
.
questId
,
this
);
this
.
getData
().
getBeginExec
().
forEach
(
e
->
getOwner
().
getServer
().
getQuestSystem
().
triggerExec
(
this
,
e
,
e
.
getParam
()));
getQuestData
().
getBeginExec
().
forEach
(
e
->
getOwner
().
getServer
().
getQuestSystem
().
triggerExec
(
this
,
e
,
e
.
getParam
()));
this
.
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_QUEST_STATE_EQUAL
,
this
.
questId
,
this
.
state
.
getValue
());
if
(
ChapterData
.
beginQuestChapterMap
.
containsKey
(
q
uestId
))
{
if
(
ChapterData
.
beginQuestChapterMap
.
containsKey
(
subQ
uestId
)){
mainQuest
.
getOwner
().
sendPacket
(
new
PacketChapterStateNotify
(
ChapterData
.
beginQuestChapterMap
.
get
(
q
uestId
).
getId
(),
ChapterData
.
beginQuestChapterMap
.
get
(
subQ
uestId
).
getId
(),
ChapterStateOuterClass
.
ChapterState
.
CHAPTER_STATE_BEGIN
));
}
Grasscutter
.
getLogger
().
debug
(
"Quest {} is started"
,
questId
);
}
public
GameMainQuest
getMainQuest
()
{
return
mainQuest
;
}
public
void
setMainQuest
(
GameMainQuest
mainQuest
)
{
this
.
mainQuest
=
mainQuest
;
}
public
Player
getOwner
()
{
return
getMainQuest
().
getOwner
();
}
public
int
getQuestId
()
{
return
questId
;
}
public
int
getMainQuestId
()
{
return
mainQuestId
;
}
public
QuestData
getData
()
{
return
questData
;
}
public
void
setConfig
(
QuestData
config
)
{
if
(
this
.
getQuestId
()
!=
config
.
getId
())
return
;
this
.
questData
=
config
;
}
public
QuestState
getState
()
{
return
state
;
}
public
void
setState
(
QuestState
state
)
{
this
.
state
=
state
;
}
public
int
getStartTime
()
{
return
startTime
;
}
public
void
setStartTime
(
int
startTime
)
{
this
.
startTime
=
startTime
;
}
public
int
getAcceptTime
()
{
return
acceptTime
;
}
public
void
setAcceptTime
(
int
acceptTime
)
{
this
.
acceptTime
=
acceptTime
;
}
//Some subQuests and talks become active when some other subQuests are unfinished (even from different MainQuests)
this
.
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_QUEST_STATE_EQUAL
,
this
.
getSubQuestId
(),
this
.
getState
().
getValue
(),
0
,
0
,
0
);
this
.
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_COND_STATE_EQUAL
,
this
.
getSubQuestId
(),
this
.
getState
().
getValue
(),
0
,
0
,
0
);
public
int
getFinishTime
()
{
return
finishTime
;
Grasscutter
.
getLogger
().
debug
(
"Quest {} is started"
,
subQuestId
);
}
public
void
setFinishTime
(
int
finishTime
)
{
this
.
finishTime
=
finishTime
;
public
String
getTriggerNameById
(
int
id
)
{
TriggerExcelConfigData
trigger
=
GameData
.
getTriggerExcelConfigDataMap
().
get
(
id
);
if
(
trigger
!=
null
)
{
String
triggerName
=
trigger
.
getTriggerName
();
return
triggerName
;
}
//return empty string if can't find trigger
return
""
;
}
public
int
[]
getFinishProgressList
()
{
return
finishProgressList
;
}
public
Player
getOwner
()
{
return
this
.
getMainQuest
().
getOwner
()
;
}
public
void
setFinishProgress
(
int
index
,
int
value
)
{
finishProgressList
[
index
]
=
value
;
}
public
void
setConfig
(
QuestData
config
)
{
if
(
getSubQuestId
()
!=
config
.
getId
())
return
;
this
.
questData
=
config
;
}
public
int
[]
getFailProgressList
(
)
{
return
failProgressList
;
}
public
void
setFinishProgress
(
int
index
,
int
value
)
{
finishProgressList
[
index
]
=
value
;
}
public
void
setFailProgress
(
int
index
,
int
value
)
{
failProgressList
[
index
]
=
value
;
}
public
void
setFailProgress
(
int
index
,
int
value
)
{
failProgressList
[
index
]
=
value
;
}
public
void
finish
()
{
this
.
state
=
QuestState
.
QUEST_STATE_FINISHED
;
this
.
finishTime
=
Utils
.
getCurrentSeconds
();
public
void
finish
()
{
this
.
state
=
QuestState
.
QUEST_STATE_FINISHED
;
this
.
finishTime
=
Utils
.
getCurrentSeconds
();
if
(
this
.
getFinishProgressList
()
!=
null
)
{
for
(
int
i
=
0
;
i
<
getFinishProgressList
().
length
;
i
++)
{
getFinishProgressList
()[
i
]
=
1
;
}
}
if
(
getFinishProgressList
()
!=
null
)
{
Arrays
.
fill
(
getFinishProgressList
(),
1
);
}
this
.
getOwner
().
getSession
().
send
(
new
PacketQuestProgressUpdateNotify
(
this
));
this
.
getOwner
().
getSession
().
send
(
new
PacketQuestListUpdateNotify
(
this
));
getOwner
().
getSession
().
send
(
new
PacketQuestProgressUpdateNotify
(
this
));
if
(
this
.
getData
().
finishParent
())
{
// This quest finishes the questline - the main quest will also save the quest to db so we dont have to call save() here
this
.
getMainQuest
().
finish
();
}
else
{
// Try and accept other quests if possible
this
.
tryAcceptQuestLine
();
this
.
save
();
}
this
.
getData
().
getFinishExec
().
forEach
(
e
->
getOwner
().
getServer
().
getQuestSystem
().
triggerExec
(
this
,
e
,
e
.
getParam
()));
if
(
getQuestData
().
finishParent
())
{
// This quest finishes the questline - the main quest will also save the quest to db, so we don't have to call save() here
getMainQuest
().
finish
();
}
this
.
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_QUEST_STATE_EQUAL
,
this
.
questId
,
this
.
state
.
getValue
());
getQuestData
().
getFinishExec
().
forEach
(
e
->
getOwner
().
getServer
().
getQuestSystem
().
triggerExec
(
this
,
e
,
e
.
getParam
()));
//Some subQuests have conditions that subQuests are finished (even from different MainQuests)
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_QUEST_STATE_EQUAL
,
this
.
subQuestId
,
this
.
state
.
getValue
(),
0
,
0
,
0
);
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_COND_STATE_EQUAL
,
this
.
subQuestId
,
this
.
state
.
getValue
(),
0
,
0
,
0
);
if
(
ChapterData
.
endQuestChapterMap
.
containsKey
(
q
uestId
))
{
if
(
ChapterData
.
endQuestChapterMap
.
containsKey
(
subQ
uestId
)){
mainQuest
.
getOwner
().
sendPacket
(
new
PacketChapterStateNotify
(
ChapterData
.
endQuestChapterMap
.
get
(
q
uestId
).
getId
(),
ChapterData
.
endQuestChapterMap
.
get
(
subQ
uestId
).
getId
(),
ChapterStateOuterClass
.
ChapterState
.
CHAPTER_STATE_END
));
}
Grasscutter
.
getLogger
().
debug
(
"Quest {} is finished"
,
questId
);
}
public
boolean
tryAcceptQuestLine
()
{
try
{
MainQuestData
questConfig
=
GameData
.
getMainQuestDataMap
().
get
(
this
.
getMainQuestId
());
for
(
SubQuestData
subQuest
:
questConfig
.
getSubQuests
())
{
GameQuest
quest
=
getMainQuest
().
getChildQuestById
(
subQuest
.
getSubId
());
if
(
quest
==
null
)
{
QuestData
questData
=
GameData
.
getQuestDataMap
().
get
(
subQuest
.
getSubId
());
if
(
questData
==
null
||
questData
.
getAcceptCond
()
==
null
||
questData
.
getAcceptCond
().
size
()
==
0
)
{
continue
;
}
int
[]
accept
=
new
int
[
questData
.
getAcceptCond
().
size
()];
// TODO
for
(
int
i
=
0
;
i
<
questData
.
getAcceptCond
().
size
();
i
++)
{
QuestCondition
condition
=
questData
.
getAcceptCond
().
get
(
i
);
boolean
result
=
getOwner
().
getServer
().
getQuestSystem
().
triggerCondition
(
this
,
condition
,
condition
.
getParamStr
(),
condition
.
getParam
());
Grasscutter
.
getLogger
().
debug
(
"Quest {} is finished"
,
subQuestId
);
}
accept
[
i
]
=
result
?
1
:
0
;
}
boolean
shouldAccept
=
LogicType
.
calculate
(
questData
.
getAcceptCondComb
(),
accept
);
//TODO
public
void
fail
()
{
this
.
state
=
QuestState
.
QUEST_STATE_FAILED
;
this
.
finishTime
=
Utils
.
getCurrentSeconds
(
);
if
(
shouldAccept
)
{
this
.
getOwner
().
getQuestManager
().
addQuest
(
questData
.
getId
());
}
}
}
}
catch
(
Exception
e
)
{
Grasscutter
.
getLogger
().
error
(
"An error occurred while trying to accept quest."
,
e
);
if
(
getFailProgressList
()
!=
null
)
{
Arrays
.
fill
(
getFailProgressList
(),
1
);
}
return
false
;
}
public
void
save
()
{
getMainQuest
().
save
();
}
getOwner
().
getSession
().
send
(
new
PacketQuestProgressUpdateNotify
(
this
));
public
Quest
toProto
()
{
Quest
.
Builder
proto
=
Quest
.
newBuilder
()
.
setQuestId
(
this
.
getQuestId
())
.
setState
(
this
.
getState
().
getValue
())
.
setParentQuestId
(
this
.
getMainQuestId
())
.
setStartTime
(
this
.
getStartTime
())
.
setStartGameTime
(
438
)
.
setAcceptTime
(
this
.
getAcceptTime
());
if
(
this
.
getFinishProgressList
()
!=
null
)
{
for
(
int
i
:
this
.
getFinishProgressList
())
{
proto
.
addFinishProgressList
(
i
);
}
}
getQuestData
().
getFailExec
().
forEach
(
e
->
getOwner
().
getServer
().
getQuestSystem
().
triggerExec
(
this
,
e
,
e
.
getParam
()));
//Some subQuests have conditions that subQuests fail (even from different MainQuests)
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_CONTENT_QUEST_STATE_EQUAL
,
this
.
subQuestId
,
this
.
state
.
getValue
(),
0
,
0
,
0
);
getOwner
().
getQuestManager
().
triggerEvent
(
QuestTrigger
.
QUEST_COND_STATE_EQUAL
,
this
.
subQuestId
,
this
.
state
.
getValue
(),
0
,
0
,
0
);
if
(
this
.
getFailProgressList
()
!=
null
)
{
for
(
int
i
:
this
.
getFailProgressList
())
{
proto
.
addFailProgressList
(
i
);
}
// Return true if ParentQuest should rewind to this childQuest
public
boolean
rewind
(
GameQuest
nextRewind
)
{
if
(
questData
.
isRewind
())
{
if
(
nextRewind
==
null
)
{
return
true
;}
// if the next isRewind subQuest is none or unstarted, reset all subQuests with order higher than this one, and restart this quest
if
(
nextRewind
.
getState
()
==
QuestState
.
QUEST_STATE_NONE
||
nextRewind
.
getState
()
==
QuestState
.
QUEST_STATE_UNSTARTED
)
{
getMainQuest
().
getChildQuests
().
values
().
stream
().
filter
(
p
->
p
.
getQuestData
().
getOrder
()
>
this
.
getQuestData
().
getOrder
()).
forEach
(
q
->
q
.
setState
(
QuestState
.
QUEST_STATE_UNSTARTED
));
this
.
start
();
return
true
;
}
}
return
proto
.
build
();
return
false
;
}
public
void
save
()
{
getMainQuest
().
save
();
}
public
Quest
toProto
()
{
Quest
.
Builder
proto
=
Quest
.
newBuilder
()
.
setQuestId
(
getSubQuestId
())
.
setState
(
getState
().
getValue
())
.
setParentQuestId
(
getMainQuestId
())
.
setStartTime
(
getStartTime
())
.
setStartGameTime
(
438
)
.
setAcceptTime
(
getAcceptTime
());
if
(
getFinishProgressList
()
!=
null
)
{
for
(
int
i
:
getFinishProgressList
())
{
proto
.
addFinishProgressList
(
i
);
}
}
if
(
getFailProgressList
()
!=
null
)
{
for
(
int
i
:
getFailProgressList
())
{
proto
.
addFailProgressList
(
i
);
}
}
return
proto
.
build
();
}
}
src/main/java/emu/grasscutter/game/quest/QuestManager.java
View file @
797afd4c
package
emu.grasscutter.game.quest
;
import
java.beans.Transient
;
import
java.util.*
;
import
java.util.function.Consumer
;
import
emu.grasscutter.Grasscutter
;
...
...
@@ -15,37 +16,134 @@ import emu.grasscutter.game.quest.enums.QuestTrigger;
import
emu.grasscutter.game.quest.enums.LogicType
;
import
emu.grasscutter.game.quest.enums.QuestState
;
import
emu.grasscutter.server.packet.send.*
;
import
emu.grasscutter.utils.Position
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectMap
;
import
it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
;
import
jdk.jshell.spi.ExecutionControl
;
import
lombok.Getter
;
public
class
QuestManager
extends
BasePlayerManager
{
private
final
Int2ObjectMap
<
GameMainQuest
>
quests
;
public
static
long
getQuestKey
(
int
mainQuestId
){
@Getter
private
final
Player
player
;
@Getter
private
Map
<
Integer
,
Integer
>
questGlobalVariables
;
@Getter
private
final
Int2ObjectMap
<
GameMainQuest
>
mainQuests
;
@Getter
private
List
<
GameQuest
>
addToQuestListUpdateNotify
;
/*
On SetPlayerBornDataReq, the server sends FinishedParentQuestNotify, with this exact
parentQuestList. Captured on Game version 2.7
Note: quest 40063 is already set to finished, with childQuest 4006406's state set to 3
*/
private
static
Set
<
Integer
>
newPlayerMainQuests
=
Set
.
of
(
303
,
318
,
348
,
349
,
350
,
351
,
416
,
500
,
501
,
502
,
503
,
504
,
505
,
506
,
507
,
508
,
509
,
20000
,
20507
,
20509
,
21004
,
21005
,
21010
,
21011
,
21016
,
21017
,
21020
,
21021
,
21025
,
40063
,
70121
,
70124
,
70511
,
71010
,
71012
,
71013
,
71015
,
71016
,
71017
,
71555
);
/*
On SetPlayerBornDataReq, the server sends ServerCondMeetQuestListUpdateNotify, with this exact
addQuestIdList. Captured on Game version 2.7
Total of 161...
*/
/*
private static Set<Integer> newPlayerServerCondMeetQuestListUpdateNotify = Set.of(3100101, 7104405, 2201601,
7100801, 1907002, 7293301, 7193801, 7293401, 7193901, 7091001, 7190501, 7090901, 7190401, 7090801, 7190301,
7195301, 7294801, 7195201, 7293001, 7094001, 7193501, 7293501, 7194001, 7293701, 7194201, 7194301, 7293801,
7194901, 7194101, 7195001, 7294501, 7294101, 7194601, 7294301, 7194801, 7091301, 7290301, 2102401, 7216801,
7190201, 7090701, 7093801, 7193301, 7292801, 7227828, 7093901, 7193401, 7292901, 7093701, 7193201, 7292701,
7082402, 7093601, 7292601, 7193101, 2102301, 7093501, 7292501, 7193001, 7093401, 7292401, 7192901, 7093301,
7292301, 7192801, 7294201, 7194701, 2100301, 7093201, 7212402, 7292201, 7192701, 7280001, 7293901, 7194401,
7093101, 7212302, 7292101, 7192601, 7093001, 7292001, 7192501, 7216001, 7195101, 7294601, 2100900, 7092901,
7291901, 7192401, 7092801, 7291801, 7192301, 2101501, 7092701, 7291701, 7192201, 7106401, 2100716, 7091801,
7290801, 7191301, 7293201, 7193701, 7094201, 7294001, 7194501, 2102290, 7227829, 7193601, 7094101, 7091401,
7290401, 7190901, 7106605, 7291601, 7192101, 7092601, 7291501, 7192001, 7092501, 7291401, 7191901, 7092401,
7291301, 7191801, 7092301, 7211402, 7291201, 7191701, 7092201, 7291101, 7191601, 7092101, 7291001, 7191501,
7092001, 7290901, 7191401, 7091901, 7290701, 7191201, 7091701, 7290601, 7191101, 7091601, 7290501, 7191001,
7091501, 7290201, 7190701, 7091201, 7190601, 7091101, 7190101, 7090601, 7090501, 7090401, 7010701, 7090301,
7090201, 7010103, 7090101
);
*/
public
static
long
getQuestKey
(
int
mainQuestId
){
QuestEncryptionKey
questEncryptionKey
=
GameData
.
getMainQuestEncryptionMap
().
get
(
mainQuestId
);
return
questEncryptionKey
!=
null
?
questEncryptionKey
.
getEncryptionKey
()
:
0L
;
}
public
QuestManager
(
Player
player
)
{
public
QuestManager
(
Player
player
)
{
super
(
player
);
this
.
quests
=
new
Int2ObjectOpenHashMap
<>();
this
.
player
=
player
;
this
.
questGlobalVariables
=
player
.
getQuestGlobalVariables
();
this
.
mainQuests
=
new
Int2ObjectOpenHashMap
<>();
this
.
addToQuestListUpdateNotify
=
new
ArrayList
<>();
}
public
void
onNewPlayerCreate
()
{
List
<
GameMainQuest
>
newQuests
=
this
.
addMultMainQuests
(
newPlayerMainQuests
);
//getPlayer().sendPacket(new PacketServerCondMeetQuestListUpdateNotify(newPlayerServerCondMeetQuestListUpdateNotify));
getPlayer
().
sendPacket
(
new
PacketFinishedParentQuestUpdateNotify
(
newQuests
));
}
public
Int2ObjectMap
<
GameMainQuest
>
getQuests
()
{
return
quests
;
public
void
onLogin
()
{
List
<
GameMainQuest
>
activeQuests
=
getActiveMainQuests
();
for
(
GameMainQuest
quest
:
activeQuests
)
{
List
<
Position
>
rewindPos
=
quest
.
rewind
();
// <pos, rotation>
if
(
rewindPos
!=
null
)
{
getPlayer
().
getPosition
().
set
(
rewindPos
.
get
(
0
));
getPlayer
().
getRotation
().
set
(
rewindPos
.
get
(
1
));
}
}
}
public
GameMainQuest
getMainQuestById
(
int
mainQuestId
)
{
return
getQuests
().
get
(
mainQuestId
);
private
List
<
GameMainQuest
>
addMultMainQuests
(
Set
<
Integer
>
mainQuestIds
)
{
List
<
GameMainQuest
>
newQuests
=
new
ArrayList
<>();
for
(
Integer
id
:
mainQuestIds
)
{
getMainQuests
().
put
(
id
.
intValue
(),
new
GameMainQuest
(
this
.
player
,
id
));
getMainQuestById
(
id
).
save
();
newQuests
.
add
(
getMainQuestById
(
id
));
}
return
newQuests
;
}
/*
Looking through mainQuests 72201-72208 and 72174, we can infer that a questGlobalVar's default value is 0
*/
public
Integer
getQuestGlobalVarValue
(
Integer
variable
)
{
return
this
.
questGlobalVariables
.
getOrDefault
(
variable
,
0
);
}
public
void
setQuestGlobalVarValue
(
Integer
variable
,
Integer
value
)
{
Integer
previousValue
=
this
.
questGlobalVariables
.
put
(
variable
,
value
);
Grasscutter
.
getLogger
().
debug
(
"Changed questGlobalVar {} value from {} to {}"
,
variable
,
previousValue
==
null
?
0
:
previousValue
,
value
);
}
public
void
incQuestGlobalVarValue
(
Integer
variable
,
Integer
inc
)
{
//
Integer
previousValue
=
this
.
questGlobalVariables
.
getOrDefault
(
variable
,
0
);
this
.
questGlobalVariables
.
put
(
variable
,
previousValue
+
inc
);
Grasscutter
.
getLogger
().
debug
(
"Incremented questGlobalVar {} value from {} to {}"
,
variable
,
previousValue
,
previousValue
+
inc
);
}
//In MainQuest 998, dec is passed as a positive integer
public
void
decQuestGlobalVarValue
(
Integer
variable
,
Integer
dec
)
{
//
Integer
previousValue
=
this
.
questGlobalVariables
.
getOrDefault
(
variable
,
0
);
this
.
questGlobalVariables
.
put
(
variable
,
previousValue
-
dec
);
Grasscutter
.
getLogger
().
debug
(
"Decremented questGlobalVar {} value from {} to {}"
,
variable
,
previousValue
,
previousValue
-
dec
);
}
public
GameMainQuest
getMainQuestById
(
int
mainQuestId
)
{
return
getMainQuests
().
get
(
mainQuestId
);
}
public
GameQuest
getQuestById
(
int
questId
)
{
QuestData
questConfig
=
GameData
.
getQuestDataMap
().
get
(
questId
);
if
(
questConfig
==
null
)
{
return
null
;
}
GameMainQuest
mainQuest
=
getQuests
().
get
(
questConfig
.
getMainId
());
GameMainQuest
mainQuest
=
get
Main
Quests
().
get
(
questConfig
.
getMainId
());
if
(
mainQuest
==
null
)
{
return
null
;
...
...
@@ -54,34 +152,34 @@ public class QuestManager extends BasePlayerManager {
return
mainQuest
.
getChildQuests
().
get
(
questId
);
}
public
void
forEachQuest
(
Consumer
<
GameQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
getQuests
().
values
())
{
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
callback
.
accept
(
quest
);
}
}
}
public
void
forEachMainQuest
(
Consumer
<
GameMainQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
getQuests
().
values
())
{
callback
.
accept
(
mainQuest
);
}
}
// TODO
public
void
forEachActiveQuest
(
Consumer
<
GameQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
getQuests
().
values
())
{
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
if
(
quest
.
getState
()
!=
QuestState
.
QUEST_STATE_FINISHED
)
{
callback
.
accept
(
quest
);
}
}
}
}
public
GameMainQuest
addMainQuest
(
QuestData
questConfig
)
{
GameMainQuest
mainQuest
=
new
GameMainQuest
(
getPlayer
(),
questConfig
.
getMainId
());
get
Quests
().
put
(
mainQuest
.
getParentQuestId
(),
mainQuest
);
public
void
forEachQuest
(
Consumer
<
GameQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
get
Main
Quests
().
values
())
{
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
callback
.
accept
(
quest
);
}
}
}
public
void
forEachMainQuest
(
Consumer
<
GameMainQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
get
Main
Quests
().
values
())
{
callback
.
accept
(
mainQuest
);
}
}
// TODO
public
void
forEachActiveQuest
(
Consumer
<
GameQuest
>
callback
)
{
for
(
GameMainQuest
mainQuest
:
get
Main
Quests
().
values
())
{
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
if
(
quest
.
getState
()
!=
QuestState
.
QUEST_STATE_FINISHED
)
{
callback
.
accept
(
quest
);
}
}
}
}
public
GameMainQuest
addMainQuest
(
QuestData
questConfig
)
{
GameMainQuest
mainQuest
=
new
GameMainQuest
(
getPlayer
(),
questConfig
.
getMainId
());
getMain
Quests
().
put
(
mainQuest
.
getParentQuestId
(),
mainQuest
);
getPlayer
().
sendPacket
(
new
PacketFinishedParentQuestUpdateNotify
(
mainQuest
));
...
...
@@ -105,18 +203,16 @@ public class QuestManager extends BasePlayerManager {
// Sub quest
GameQuest
quest
=
mainQuest
.
getChildQuestById
(
questId
);
if
(
quest
!=
null
)
{
return
null
;
}
// Create
quest
=
new
GameQuest
(
mainQuest
,
questConfig
);
// Forcefully start
quest
.
start
();
// Save main quest
mainQuest
.
save
();
// Send packet
getPlayer
().
sendPacket
(
new
PacketQuestListUpdateNotify
(
quest
));
// Send packet
getPlayer
().
sendPacket
(
new
PacketQuestListUpdateNotify
(
mainQuest
.
getChildQuests
().
values
().
stream
()
.
filter
(
p
->
p
.
getState
()
!=
QuestState
.
QUEST_STATE_UNSTARTED
)
.
toList
()));
return
quest
;
}
...
...
@@ -136,55 +232,81 @@ public class QuestManager extends BasePlayerManager {
triggerEvent
(
condType
,
""
,
params
);
}
public
void
triggerEvent
(
QuestTrigger
condType
,
String
paramStr
,
int
...
params
)
{
//TODO
public
void
triggerEvent
(
QuestTrigger
condType
,
String
paramStr
,
int
...
params
)
{
Grasscutter
.
getLogger
().
debug
(
"Trigger Event {}, {}, {}"
,
condType
,
paramStr
,
params
);
Set
<
GameQuest
>
changedQuests
=
new
HashSet
<>();
this
.
forEachActiveQuest
(
quest
->
{
QuestData
data
=
quest
.
getData
();
for
(
int
i
=
0
;
i
<
data
.
getFinishCond
().
size
();
i
++)
{
if
(
quest
.
getFinishProgressList
()
==
null
||
quest
.
getFinishProgressList
().
length
==
0
||
quest
.
getFinishProgressList
()[
i
]
==
1
)
{
continue
;
List
<
GameMainQuest
>
checkMainQuests
=
this
.
getMainQuests
().
values
().
stream
()
.
filter
(
i
->
i
.
getState
()
!=
ParentQuestState
.
PARENT_QUEST_STATE_FINISHED
)
.
toList
();
switch
(
condType
){
//accept Conds
case
QUEST_COND_STATE_EQUAL:
case
QUEST_COND_STATE_NOT_EQUAL:
case
QUEST_COND_COMPLETE_TALK:
case
QUEST_COND_LUA_NOTIFY:
case
QUEST_COND_QUEST_VAR_EQUAL:
case
QUEST_COND_QUEST_VAR_GREATER:
case
QUEST_COND_QUEST_VAR_LESS:
case
QUEST_COND_PLAYER_LEVEL_EQUAL_GREATER:
case
QUEST_COND_QUEST_GLOBAL_VAR_EQUAL:
case
QUEST_COND_QUEST_GLOBAL_VAR_GREATER:
case
QUEST_COND_QUEST_GLOBAL_VAR_LESS:
for
(
GameMainQuest
mainquest
:
checkMainQuests
)
{
mainquest
.
tryAcceptSubQuests
(
condType
,
paramStr
,
params
);
}
break
;
QuestCondition
condition
=
data
.
getFinishCond
().
get
(
i
);
if
(
condition
.
getType
()
!=
condType
)
{
continue
;
//fail Conds
case
QUEST_CONTENT_NOT_FINISH_PLOT:
for
(
GameMainQuest
mainquest
:
checkMainQuests
)
{
mainquest
.
tryFailSubQuests
(
condType
,
paramStr
,
params
)
;
}
boolean
result
=
getPlayer
().
getServer
().
getQuestSystem
().
triggerContent
(
quest
,
condition
,
paramStr
,
params
);
if
(
result
)
{
quest
.
getFinishProgressList
()[
i
]
=
1
;
changedQuests
.
add
(
quest
);
break
;
//finish Conds
case
QUEST_CONTENT_COMPLETE_TALK:
case
QUEST_CONTENT_FINISH_PLOT:
case
QUEST_CONTENT_COMPLETE_ANY_TALK:
case
QUEST_CONTENT_LUA_NOTIFY:
case
QUEST_CONTENT_QUEST_VAR_EQUAL:
case
QUEST_CONTENT_QUEST_VAR_GREATER:
case
QUEST_CONTENT_QUEST_VAR_LESS:
case
QUEST_CONTENT_ENTER_DUNGEON:
case
QUEST_CONTENT_ENTER_ROOM:
case
QUEST_CONTENT_INTERACT_GADGET:
case
QUEST_CONTENT_TRIGGER_FIRE:
case
QUEST_CONTENT_UNLOCK_TRANS_POINT:
for
(
GameMainQuest
mainQuest
:
checkMainQuests
)
{
mainQuest
.
tryFinishSubQuests
(
condType
,
paramStr
,
params
);
}
}
});
for
(
GameQuest
quest
:
changedQuests
)
{
LogicType
logicType
=
quest
.
getData
().
getFailCondComb
();
int
[]
progress
=
quest
.
getFinishProgressList
();
// Handle logical comb
boolean
finish
=
LogicType
.
calculate
(
logicType
,
progress
);
// Finish
if
(
finish
)
{
quest
.
finish
();
}
else
{
getPlayer
().
sendPacket
(
new
PacketQuestProgressUpdateNotify
(
quest
));
quest
.
save
();
}
break
;
//finish Or Fail Conds
case
QUEST_CONTENT_GAME_TIME_TICK:
case
QUEST_CONTENT_QUEST_STATE_EQUAL:
case
QUEST_CONTENT_ADD_QUEST_PROGRESS:
case
QUEST_CONTENT_LEAVE_SCENE:
for
(
GameMainQuest
mainQuest
:
checkMainQuests
)
{
mainQuest
.
tryFailSubQuests
(
condType
,
paramStr
,
params
);
mainQuest
.
tryFinishSubQuests
(
condType
,
paramStr
,
params
);
}
break
;
//QUEST_EXEC are handled directly by each subQuest
//Unused
case
QUEST_CONTENT_QUEST_STATE_NOT_EQUAL:
case
QUEST_COND_PLAYER_CHOOSE_MALE:
default
:
Grasscutter
.
getLogger
().
error
(
"Unhandled QuestTrigger {}"
,
condType
);
}
}
if
(
this
.
addToQuestListUpdateNotify
.
size
()
!=
0
){
this
.
getPlayer
().
getSession
().
send
(
new
PacketQuestListUpdateNotify
(
this
.
addToQuestListUpdateNotify
));
this
.
addToQuestListUpdateNotify
.
clear
();
}
}
public
List
<
QuestGroupSuite
>
getSceneGroupSuite
(
int
sceneId
)
{
return
getQuests
().
values
().
stream
()
return
get
Main
Quests
().
values
().
stream
()
.
filter
(
i
->
i
.
getState
()
!=
ParentQuestState
.
PARENT_QUEST_STATE_FINISHED
)
.
map
(
GameMainQuest:
:
getQuestGroupSuites
)
.
filter
(
Objects:
:
nonNull
)
...
...
@@ -198,12 +320,16 @@ public class QuestManager extends BasePlayerManager {
for
(
GameMainQuest
mainQuest
:
quests
)
{
mainQuest
.
setOwner
(
this
.
getPlayer
());
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
quest
.
setMainQuest
(
mainQuest
);
quest
.
setConfig
(
GameData
.
getQuestDataMap
().
get
(
quest
.
getQuestId
()));
}
for
(
GameQuest
quest
:
mainQuest
.
getChildQuests
().
values
())
{
quest
.
setMainQuest
(
mainQuest
);
quest
.
setConfig
(
GameData
.
getQuestDataMap
().
get
(
quest
.
get
Sub
QuestId
()));
}
this
.
getQuests
().
put
(
mainQuest
.
getParentQuestId
(),
mainQuest
);
}
this
.
getMainQuests
().
put
(
mainQuest
.
getParentQuestId
(),
mainQuest
);
}
}
public
List
<
GameMainQuest
>
getActiveMainQuests
()
{
return
getMainQuests
().
values
().
stream
().
filter
(
p
->
!
p
.
isFinished
()).
toList
();
}
}
src/main/java/emu/grasscutter/game/quest/QuestSystem.java
View file @
797afd4c
...
...
@@ -65,8 +65,8 @@ public class QuestSystem extends BaseGameSystem {
public
boolean
triggerCondition
(
GameQuest
quest
,
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
QuestBaseHandler
handler
=
condHandlers
.
get
(
condition
.
getType
().
getValue
());
if
(
handler
==
null
||
quest
.
getData
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger condition {} at {}"
,
condition
.
getType
().
getValue
(),
quest
.
getData
());
if
(
handler
==
null
||
quest
.
get
Quest
Data
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger condition {} at {}"
,
condition
.
getType
().
getValue
(),
quest
.
get
Quest
Data
());
return
false
;
}
...
...
@@ -76,8 +76,8 @@ public class QuestSystem extends BaseGameSystem {
public
boolean
triggerContent
(
GameQuest
quest
,
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
QuestBaseHandler
handler
=
contHandlers
.
get
(
condition
.
getType
().
getValue
());
if
(
handler
==
null
||
quest
.
getData
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger content {} at {}"
,
condition
.
getType
().
getValue
(),
quest
.
getData
());
if
(
handler
==
null
||
quest
.
get
Quest
Data
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger content {} at {}"
,
condition
.
getType
().
getValue
(),
quest
.
get
Quest
Data
());
return
false
;
}
...
...
@@ -87,8 +87,8 @@ public class QuestSystem extends BaseGameSystem {
public
boolean
triggerExec
(
GameQuest
quest
,
QuestExecParam
execParam
,
String
...
params
)
{
QuestExecHandler
handler
=
execHandlers
.
get
(
execParam
.
getType
().
getValue
());
if
(
handler
==
null
||
quest
.
getData
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger exec {} at {}"
,
execParam
.
getType
().
getValue
(),
quest
.
getData
());
if
(
handler
==
null
||
quest
.
get
Quest
Data
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Could not trigger exec {} at {}"
,
execParam
.
getType
().
getValue
(),
quest
.
get
Quest
Data
());
return
false
;
}
...
...
src/main/java/emu/grasscutter/game/quest/RewindData.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest
;
import
lombok.Data
;
import
lombok.Getter
;
import
java.util.List
;
@Data
public
class
RewindData
{
AvatarData
avatar
;
List
<
Npc
>
npcs
;
@Data
public
static
class
AvatarData
{
@Getter
private
String
pos
;
}
@Data
private
static
class
Npc
{
private
String
script
;
private
int
room_id
;
private
int
data_index
;
private
int
id
;
private
String
pos
;
private
int
scene_id
;
private
String
alias
;
}
}
src/main/java/emu/grasscutter/game/quest/conditions/ConditionCompleteTalk.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.GameData
;
import
emu.grasscutter.data.binout.MainQuestData
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.quest.GameMainQuest
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_COMPLETE_TALK
)
public
class
ConditionCompleteTalk
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
GameMainQuest
checkMainQuest
=
quest
.
getOwner
().
getQuestManager
().
getMainQuestById
(
condition
.
getParam
()[
0
]/
100
);
if
(
checkMainQuest
==
null
||
GameData
.
getMainQuestDataMap
().
get
(
checkMainQuest
.
getParentQuestId
()).
getTalks
()
==
null
)
{
Grasscutter
.
getLogger
().
debug
(
"Warning: mainQuest {} hasn't been started yet, or has no talks"
,
condition
.
getParam
()[
0
]/
100
);
return
false
;
}
MainQuestData
.
TalkData
talkData
=
checkMainQuest
.
getTalks
().
get
(
Integer
.
valueOf
(
params
[
0
]));
return
talkData
!=
null
||
checkMainQuest
.
getChildQuestById
(
params
[
0
])
!=
null
;
}
}
src/main/java/emu/grasscutter/game/quest/conditions/ConditionLuaNotify.java
View file @
797afd4c
...
...
@@ -8,7 +8,7 @@ import emu.grasscutter.game.quest.handlers.QuestBaseHandler;
@QuestValue
(
QuestTrigger
.
QUEST_COND_LUA_NOTIFY
)
public
class
ConditionLuaNotify
extends
QuestBaseHandler
{
//Wrong implementation. Example: 7010226 has no paramStr
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
return
condition
.
getParam
()[
0
]
==
Integer
.
parseInt
(
paramStr
);
...
...
src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarEqual.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_QUEST_GLOBAL_VAR_EQUAL
)
public
class
ConditionQuestGlobalVarEqual
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
Integer
questGlobalVarValue
=
quest
.
getMainQuest
().
getQuestManager
().
getQuestGlobalVarValue
(
Integer
.
valueOf
(
params
[
0
]));
Grasscutter
.
getLogger
().
debug
(
"questGlobarVar {} : {}"
,
params
[
0
],
questGlobalVarValue
);
return
questGlobalVarValue
.
intValue
()
==
params
[
1
];
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarGreater.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_QUEST_GLOBAL_VAR_GREATER
)
public
class
ConditionQuestGlobalVarGreater
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
Integer
questGlobalVarValue
=
quest
.
getMainQuest
().
getQuestManager
().
getQuestGlobalVarValue
(
Integer
.
valueOf
(
params
[
0
]));
Grasscutter
.
getLogger
().
debug
(
"questGlobarVar {} : {}"
,
params
[
0
],
questGlobalVarValue
);
return
questGlobalVarValue
.
intValue
()
>
params
[
1
];
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestGlobalVarLess.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.player.Player
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_QUEST_GLOBAL_VAR_LESS
)
public
class
ConditionQuestGlobalVarLess
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
Integer
questGlobalVarValue
=
quest
.
getMainQuest
().
getQuestManager
().
getQuestGlobalVarValue
(
Integer
.
valueOf
(
params
[
0
]));
Grasscutter
.
getLogger
().
debug
(
"questGlobarVar {} : {}"
,
params
[
0
],
questGlobalVarValue
);
return
questGlobalVarValue
.
intValue
()
<
params
[
1
];
}
}
\ No newline at end of file
src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarEqual.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.quest.GameMainQuest
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_QUEST_VAR_EQUAL
)
public
class
ConditionQuestVarEqual
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
int
questVarValue
=
quest
.
getMainQuest
().
getQuestVars
()[
params
[
0
]];
Grasscutter
.
getLogger
().
debug
(
"questVar {} : {}"
,
params
[
0
],
questVarValue
);
return
questVarValue
==
params
[
1
];
}
}
src/main/java/emu/grasscutter/game/quest/conditions/ConditionQuestVarGreater.java
0 → 100644
View file @
797afd4c
package
emu.grasscutter.game.quest.conditions
;
import
emu.grasscutter.Grasscutter
;
import
emu.grasscutter.data.excels.QuestData
;
import
emu.grasscutter.game.quest.GameMainQuest
;
import
emu.grasscutter.game.quest.GameQuest
;
import
emu.grasscutter.game.quest.QuestValue
;
import
emu.grasscutter.game.quest.enums.QuestTrigger
;
import
emu.grasscutter.game.quest.handlers.QuestBaseHandler
;
@QuestValue
(
QuestTrigger
.
QUEST_COND_QUEST_VAR_GREATER
)
public
class
ConditionQuestVarGreater
extends
QuestBaseHandler
{
@Override
public
boolean
execute
(
GameQuest
quest
,
QuestData
.
QuestCondition
condition
,
String
paramStr
,
int
...
params
)
{
int
questVarValue
=
quest
.
getMainQuest
().
getQuestVars
()[
params
[
0
]];
Grasscutter
.
getLogger
().
debug
(
"questVar {} : {}"
,
params
[
0
],
questVarValue
);
return
questVarValue
>
params
[
1
];
}
}
Prev
1
2
3
4
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment