Skip to content

Commit

Permalink
feat: add "Sequential Task Completion" quest setting (and chapter def…
Browse files Browse the repository at this point in the history
…ault)

When true, tasks in the quest must be completed in the order they were
added to the quest. Later tasks won't even be shown (outside edit mode) in
the quest view panel until previous tasks are completed.

FTBTeam/FTB-Mods-Issues#962
  • Loading branch information
desht committed Nov 13, 2023
1 parent ae1b891 commit e6080c4
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import dev.ftb.mods.ftbquests.quest.QuestObjectBase;
import dev.ftb.mods.ftbquests.quest.reward.Reward;
import dev.ftb.mods.ftbquests.quest.reward.RewardAutoClaim;
import dev.ftb.mods.ftbquests.quest.task.Task;
import dev.ftb.mods.ftbquests.quest.theme.QuestTheme;
import dev.ftb.mods.ftbquests.quest.theme.property.ThemeProperties;
import it.unimi.dsi.fastutil.longs.Long2IntMap;
Expand Down Expand Up @@ -167,10 +168,15 @@ public void addWidgets() {

int bsize = 18;

quest.getTasks().stream().map(task -> new TaskButton(panelTasks, task)).forEach(b -> {
panelTasks.add(b);
b.setSize(bsize, bsize);
});
boolean seq = quest.getRequireSequentialTasks();
for (Task task : quest.getTasks()) {
TaskButton taskButton = new TaskButton(panelTasks, task);
panelTasks.add(taskButton);
taskButton.setSize(bsize, bsize);
if (!canEdit && seq && !questScreen.file.selfTeamData.isCompleted(task)) {
break;
}
}

if (!canEdit && panelTasks.getWidgets().isEmpty()) {
DisabledButtonTextField noTasks = new DisabledButtonTextField(panelTasks, Component.translatable("ftbquests.gui.no_tasks"));
Expand Down
11 changes: 11 additions & 0 deletions common/src/main/java/dev/ftb/mods/ftbquests/quest/Chapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public final class Chapter extends QuestObject {
private boolean hideQuestUntilDepsVisible;
private boolean defaultRepeatable;
private Tristate consumeItems;
private boolean requireSequentialTasks;

public Chapter(long id, BaseQuestFile file, ChapterGroup group) {
this(id, file, group, "");
Expand All @@ -67,6 +68,7 @@ public Chapter(long id, BaseQuestFile file, ChapterGroup group, String filename)
hideQuestDetailsUntilStartable = false;
defaultRepeatable = false;
consumeItems = Tristate.DEFAULT;
requireSequentialTasks = false;
}

public void setDefaultQuestShape(String defaultQuestShape) {
Expand Down Expand Up @@ -108,6 +110,10 @@ public boolean isDefaultRepeatable() {
return defaultRepeatable;
}

public boolean isRequireSequentialTasks() {
return requireSequentialTasks;
}

public List<Quest> getQuests() {
return Collections.unmodifiableList(quests);
}
Expand Down Expand Up @@ -174,6 +180,7 @@ public void writeData(CompoundTag nbt) {
if (hideQuestDetailsUntilStartable) nbt.putBoolean("hide_quest_details_until_startable", true);
if (hideQuestUntilDepsVisible) nbt.putBoolean("hide_quest_until_deps_visible", true);
if (defaultRepeatable) nbt.putBoolean("default_repeatable_quest", true);
if (requireSequentialTasks) nbt.putBoolean("require_sequential_tasks", true);
}

@Override
Expand Down Expand Up @@ -217,6 +224,7 @@ public void readData(CompoundTag nbt) {
hideQuestDetailsUntilStartable = nbt.getBoolean("hide_quest_details_until_startable");
hideQuestUntilDepsVisible = nbt.getBoolean("hide_quest_until_deps_visible");
defaultRepeatable = nbt.getBoolean("default_repeatable_quest");
requireSequentialTasks = nbt.getBoolean("require_sequential_tasks");
}

@Override
Expand All @@ -238,6 +246,7 @@ public void writeNetData(FriendlyByteBuf buffer) {
flags = Bits.setFlag(flags, 0x10, defaultRepeatable);
flags = Bits.setFlag(flags, 0x20, consumeItems != Tristate.DEFAULT);
flags = Bits.setFlag(flags, 0x40, consumeItems == Tristate.TRUE);
flags = Bits.setFlag(flags, 0x80, requireSequentialTasks);
buffer.writeVarInt(flags);
}

Expand All @@ -263,6 +272,7 @@ public void readNetData(FriendlyByteBuf buffer) {
hideQuestUntilDepsVisible = Bits.getFlag(flags, 0x08);
defaultRepeatable = Bits.getFlag(flags, 0x10);
consumeItems = Bits.getFlag(flags, 0x20) ? Bits.getFlag(flags, 0x40) ? Tristate.TRUE : Tristate.FALSE : Tristate.DEFAULT;
requireSequentialTasks = Bits.getFlag(flags, 0x80);
}

public int getIndex() {
Expand Down Expand Up @@ -420,6 +430,7 @@ public void fillConfigGroup(ConfigGroup config) {
misc.addEnum("progression_mode", progressionMode, v -> progressionMode = v, ProgressionMode.NAME_MAP);
misc.addBool("default_repeatable", defaultRepeatable, v -> defaultRepeatable = v, false);
misc.addTristate("consume_items", consumeItems, v -> consumeItems = v);
misc.addBool("require_sequential_tasks", requireSequentialTasks, v -> requireSequentialTasks = v, false);
}

@Override
Expand Down
15 changes: 13 additions & 2 deletions common/src/main/java/dev/ftb/mods/ftbquests/quest/Quest.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public final class Quest extends QuestObject implements Movable {
private Tristate canRepeat;
private boolean invisible; // invisible to players (not the same as hidden!)
private int invisibleUntilTasks; // invisible until at least X number of tasks have been completed
private Tristate requireSequentialTasks;

private Component cachedSubtitle = null;
private List<Component> cachedDescription = null;
Expand Down Expand Up @@ -104,6 +105,7 @@ public Quest(long id, Chapter chapter) {
ignoreRewardBlocking = false;
progressionMode = ProgressionMode.DEFAULT;
dependantIDs = new HashSet<>();
requireSequentialTasks = Tristate.DEFAULT;
}

@Override
Expand All @@ -126,7 +128,7 @@ public long getParentID() {
return chapter.id;
}

public Collection<Task> getTasks() {
public List<Task> getTasks() {
return Collections.unmodifiableList(tasks);
}

Expand Down Expand Up @@ -199,6 +201,10 @@ public boolean isOptionalForProgression() {
return isOptional();
}

public boolean getRequireSequentialTasks() {
return requireSequentialTasks.get(chapter.isRequireSequentialTasks());
}

@Override
public void writeData(CompoundTag nbt) {
super.writeData(nbt);
Expand Down Expand Up @@ -285,6 +291,7 @@ public void writeData(CompoundTag nbt) {
}

hideDetailsUntilStartable.write(nbt, "hide_details_until_startable");
requireSequentialTasks.write(nbt, "require_sequential_tasks");
}

@Override
Expand Down Expand Up @@ -346,6 +353,7 @@ public void readData(CompoundTag nbt) {
ignoreRewardBlocking = nbt.getBoolean("ignore_reward_blocking");
progressionMode = ProgressionMode.NAME_MAP.get(nbt.getString("progression_mode"));
hideDetailsUntilStartable = Tristate.read(nbt, "hide_details_until_startable");
requireSequentialTasks = Tristate.read(nbt, "require_sequential_tasks");
}

@Override
Expand All @@ -368,6 +376,8 @@ public void writeNetData(FriendlyByteBuf buffer) {
flags = Bits.setFlag(flags, 0x1000, hideDetailsUntilStartable == Tristate.TRUE);
flags = Bits.setFlag(flags, 0x2000, canRepeat != Tristate.DEFAULT);
flags = Bits.setFlag(flags, 0x4000, canRepeat == Tristate.TRUE);
flags = Bits.setFlag(flags, 0x8000, requireSequentialTasks != Tristate.DEFAULT);
flags = Bits.setFlag(flags, 0x10000, requireSequentialTasks == Tristate.TRUE);
buffer.writeVarInt(flags);

hideUntilDepsVisible.write(buffer);
Expand Down Expand Up @@ -433,7 +443,6 @@ public void readNetData(FriendlyByteBuf buffer) {
}

guidePage = Bits.getFlag(flags, 0x08) ? buffer.readUtf(Short.MAX_VALUE) : "";
//customClick = Bits.getFlag(flags, 32) ? data.readString() : "";

minRequiredDependencies = buffer.readVarInt();
dependencyRequirement = DependencyRequirement.NAME_MAP.read(buffer);
Expand All @@ -457,6 +466,7 @@ public void readNetData(FriendlyByteBuf buffer) {
optional = Bits.getFlag(flags, 0x100);
invisibleUntilTasks = Bits.getFlag(flags, 0x400) ? buffer.readVarInt() : 0;
hideDetailsUntilStartable = Bits.getFlag(flags, 0x800) ? Bits.getFlag(flags, 0x1000) ? Tristate.TRUE : Tristate.FALSE : Tristate.DEFAULT;
requireSequentialTasks = Bits.getFlag(flags, 0x8000) ? Bits.getFlag(flags, 0x10000) ? Tristate.TRUE : Tristate.FALSE : Tristate.DEFAULT;

progressionMode = ProgressionMode.NAME_MAP.read(buffer);
}
Expand Down Expand Up @@ -656,6 +666,7 @@ public void onClicked(MouseButton button, ConfigCallback callback) {
misc.addBool("optional", optional, v -> optional = v, false);
misc.addBool("ignore_reward_blocking", ignoreRewardBlocking, v -> ignoreRewardBlocking = v, false);
misc.addEnum("progression_mode", progressionMode, v -> progressionMode = v, ProgressionMode.NAME_MAP);
misc.addTristate("require_sequential_tasks", requireSequentialTasks, v -> requireSequentialTasks = v);
}

public boolean shouldHideDependencyLines() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public String formatProgress(TeamData teamData, long progress) {

@Override
public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) {
if (!teamData.isCompleted(this) && canSubmit(teamData, player)) {
if (!teamData.isCompleted(this) && checkTaskSequence(teamData) && canSubmit(teamData, player)) {
teamData.setProgress(this, 1L);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void readNetData(FriendlyByteBuf buffer) {

@Override
public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) {
if (check != null && !teamData.isCompleted(this)) {
if (check != null && checkTaskSequence(teamData) && !teamData.isCompleted(this)) {
check.check(new Data(this, teamData), player);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public ItemStack insert(TeamData teamData, ItemStack stack, boolean simulate) {

@Override
public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) {
if (taskScreenOnly || teamData.isCompleted(this) || itemStack.getItem() instanceof MissingItem || craftedItem.getItem() instanceof MissingItem) {
if (taskScreenOnly || !checkTaskSequence(teamData) || teamData.isCompleted(this) || itemStack.getItem() instanceof MissingItem || craftedItem.getItem() instanceof MissingItem) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public int autoSubmitOnPlayerTick() {

@Override
public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) {
if (teamData.isCompleted(this)) {
if (teamData.isCompleted(this) || !checkTaskSequence(teamData)) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,15 @@ public final void submitTask(TeamData teamData, ServerPlayer player) {
submitTask(teamData, player, ItemStack.EMPTY);
}

protected final boolean checkTaskSequence(TeamData teamData) {
if (quest.getRequireSequentialTasks()) {
int idx = quest.getTasks().indexOf(this);
return idx >= 0 && (idx == 0 || teamData.isCompleted(quest.getTasks().get(idx - 1)));
} else {
return true;
}
}

public boolean checkOnLogin() {
return !consumesResources();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ public static int getLevelForExperience(int targetXp) {

@Override
public void submitTask(TeamData teamData, ServerPlayer player, ItemStack craftedItem) {
if (!checkTaskSequence(teamData)) {
return;
}

int add = (int) Math.min(points ? getPlayerXP(player) : player.experienceLevel, Math.min(value - teamData.getProgress(this), Integer.MAX_VALUE));

if (add <= 0) {
Expand Down
4 changes: 4 additions & 0 deletions common/src/main/resources/assets/ftbquests/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@
"ftbquests.quest.min_required_header": "%d required",
"ftbquests.quest.hidden_quests_footer": "%d hidden",
"ftbquests.quest.misc.progression_mode": "Progression Mode",
"ftbquests.quest.misc.require_sequential_tasks": "Sequential Task Completion",
"ftbquests.quest.misc.require_sequential_tasks.tooltip": "When true, tasks must be completed in the strict order in which they were added to the quest\nDefault means to use chapter setting",
"ftbquests.chapter.misc.require_sequential_tasks": "Sequential Task Completion",
"ftbquests.chapter.misc.require_sequential_tasks.tooltip": "When true, tasks must be completed in the strict order in which they were added to the quest",
"ftbquests.quest.visibility.hide_details_until_startable": "Hide Details Until Startable",
"ftbquests.quest.visibility.hide_details_until_startable.tooltip": "If true, then quest details (text and tasks) can't be viewed until the quest can be started",
"ftbquests.chapter_group": "Chapter Group",
Expand Down

0 comments on commit e6080c4

Please sign in to comment.