Skip to content

Commit

Permalink
Quest refactoring completed; tasks need testing
Browse files Browse the repository at this point in the history
  • Loading branch information
jwvhewitt committed Jan 6, 2024
1 parent 5fb62d1 commit dc97366
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 145 deletions.
2 changes: 1 addition & 1 deletion game/content/ghplots/dd_homebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def custom_init(self, nart):
)

self.add_sub_plot(nart, "DZD_SKIPPYSNIGHTOUT")
# self.add_sub_plot(nart, "WMWO_IRON_FIST", elements={"OCCUPIER": gears.factions.BioCorp, "RESISTANCE_FACTION": gears.factions.TerranFederation})
self.add_sub_plot(nart, "WMWO_IRON_FIST", elements={"OCCUPIER": gears.factions.BioCorp, "RESISTANCE_FACTION": gears.factions.TerranFederation})

self.intro_ready = True

Expand Down
131 changes: 62 additions & 69 deletions game/content/ghplots/ghquests.py

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions game/content/ghplots/warplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def custom_init(self, nart):
oc1 = quests.QuestOutcome(
ghquests.VERB_FORTIFY, target=self.elements[RESISTANCE_FACTION],
involvement=ghchallenges.InvolvedMetroFactionNPCs(self.elements["METROSCENE"], self.elements["OCCUPIER"]),
effect=self._occupier_wins, loss_effect=self._occupier_loses,
win_effect=self._occupier_wins, loss_effect=self._occupier_loses,
lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
Expand All @@ -79,7 +79,7 @@ def custom_init(self, nart):
ghquests.VERB_EXPEL, target=self.elements[OCCUPIER],
involvement=ghchallenges.InvolvedMetroNoFriendToFactionNPCs(self.elements["METROSCENE"],
self.elements["OCCUPIER"]),
effect=self._occupier_loses, loss_effect=self._occupier_wins, lore=[
win_effect=self._occupier_loses, loss_effect=self._occupier_wins, lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
quests.TEXT_LORE_HINT: "life under {OCCUPIER} has been unbearable".format(**self.elements),
Expand Down Expand Up @@ -123,16 +123,16 @@ class OccupationCrushDissent(Plot):
def custom_init(self, nart):
# The invading faction is going to try and crush dissent in this region. The locals are going to try to resist
# this as well as they can.
self.expiration = plotutility.RulingFactionExpiration(self.elements["METROSCENE"], self.elements["OCCUPIER"])
#self.expiration = plotutility.RulingFactionExpiration(self.elements["METROSCENE"], self.elements["OCCUPIER"])
if RESISTANCE_FACTION not in self.elements:
self.elements[RESISTANCE_FACTION] = gears.factions.Circle(
nart.camp, parent_faction=self.elements.get(ORIGINAL_FACTION)
)

oc1 = quests.QuestOutcome(
ghquests.VERB_REPRESS, target=self.elements[RESISTANCE_FACTION],
ghquests.VERB_REPRESS, target=RESISTANCE_FACTION,
involvement=ghchallenges.InvolvedMetroFactionNPCs(self.elements["METROSCENE"], self.elements["OCCUPIER"]),
effect=self._occupier_wins, loss_effect=self._resistance_wins,
win_effect=self._occupier_wins, loss_effect=self._resistance_wins,
lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
Expand All @@ -149,10 +149,10 @@ def custom_init(self, nart):
)

oc2 = quests.QuestOutcome(
ghquests.VERB_EXPEL, target=self.elements[OCCUPIER],
ghquests.VERB_EXPEL, target=OCCUPIER,
involvement=ghchallenges.InvolvedMetroNoFriendToFactionNPCs(self.elements["METROSCENE"],
self.elements["OCCUPIER"]),
effect=self._resistance_wins, loss_effect=self._occupier_wins, lore=[
win_effect=self._resistance_wins, loss_effect=self._occupier_wins, lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
quests.TEXT_LORE_HINT: "life under {OCCUPIER} has been unbearable".format(**self.elements),
Expand Down Expand Up @@ -210,7 +210,7 @@ def custom_init(self, nart):
oc1 = quests.QuestOutcome(
ghquests.VERB_FORTIFY, target=self.elements[RESISTANCE_FACTION],
involvement=ghchallenges.InvolvedMetroFactionNPCs(self.elements["METROSCENE"], self.elements["OCCUPIER"]),
effect=self._occupier_wins, loss_effect=self._occupier_loses,
win_effect=self._occupier_wins, loss_effect=self._occupier_loses,
lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
Expand All @@ -230,7 +230,7 @@ def custom_init(self, nart):
ghquests.VERB_EXPEL, target=self.elements[OCCUPIER],
involvement=ghchallenges.InvolvedMetroNoFriendToFactionNPCs(self.elements["METROSCENE"],
self.elements["OCCUPIER"]),
effect=self._occupier_loses, loss_effect=self._occupier_wins, lore=[
win_effect=self._occupier_loses, loss_effect=self._occupier_wins, lore=[
quests.QuestLore(
ghquests.LORECAT_OUTCOME, texts={
quests.TEXT_LORE_HINT: "life under {OCCUPIER} has been unbearable".format(**self.elements),
Expand Down
4 changes: 4 additions & 0 deletions gears/factions.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ def __str__(self):
return self.name


def is_a_faction(maybe_fac):
return hasattr(maybe_fac, "get_faction_tag")


class FactionRelations(object):
ALLY = 1
NEUTRAL = 0
Expand Down
41 changes: 0 additions & 41 deletions pbge/kwests.py

This file was deleted.

72 changes: 47 additions & 25 deletions pbge/quests.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class QuestPlot(plots.Plot):
quest_record = None

def __init__(self, nart, pstate):
self.quest_record = QuestRecord(pstate.elements.get(QUEST_ELEMENT_ID))
self.quest_record = QuestRecord(pstate.elements.get(QUEST_ELEMENT_ID), pstate)
super().__init__(nart, pstate)

def t_UPDATE(self, camp):
Expand Down Expand Up @@ -86,7 +86,10 @@ def is_involved(self, camp, npc):

class LoreRevealer:
# An object that can be used as the "effect" for a waypoint or dialogue offer that will reveal the provided lore.
# TODO: What is loreset all about? Find out and describe its use in a comment.
# lores should be a list. Hence the "s". This way, a single conversation offer can reveal multiple pieces of lore.
# loreset is a set of lore to reveal, usually the list of "orphaned" lore held by the lore handler plot. As lore
# gets revealed it is removed from this set. When all the lore is revealed, the lore handler will typically
# deactivate itself.
def __init__(self, lores, quest, loreset=None):
self.lores = lores
self.quest = quest
Expand Down Expand Up @@ -129,7 +132,9 @@ def __str__(self):

class QuestConclusionMethodWrapper:
# An object that automatically gets added to the root plot to listen for conclusions being concluded.
# TODO: Figure out if this class is really necessary. It doesn't seem to do much.
# Because we're attaching it after the root plot has been instantiated, it isn't a proper method.
# I could use the types module to add a bound method, but because this also calls the outcome_fun
# and ends the plot (usually) I figure this way of doing things is just as good.
def __init__(self, root_plot: plots.Plot, outcome_fun, end_plot=True):
self.root_plot = root_plot
self.outcome_fun = outcome_fun
Expand Down Expand Up @@ -167,43 +172,52 @@ def __init__(
def build(self, nart, root_plot: plots.Plot):
# Start constructing a quest starting with root_plot as the main controller.
random.shuffle(self.outcomes)
for numb, outc in enumerate(self.outcomes):
for numa, outc in enumerate(self.outcomes):
print("Building {}".format(outc))
primary_conclusion = None
main_quest_line = list()
for c_label in self.conclusion_series:
for numb, c_label in enumerate(self.conclusion_series):
# Attempt to load a conclusion of this type.
if c_label.isidentifier():
ident = "{}_{}_{}".format(c_label, str(numa), str(numb))
else:
ident = "CONCLUSION_{}_{}".format(numa, numb)

if primary_conclusion:
conc = self.extend(nart, primary_conclusion, c_label, {LORE_SET_ELEMENT_ID: primary_conclusion.quest_record.needed_lore, OUTCOME_ELEMENT_ID: outc})
conc = self.extend(nart, primary_conclusion, c_label, {LORE_SET_ELEMENT_ID: primary_conclusion.quest_record.needed_lore, OUTCOME_ELEMENT_ID: outc}, spident=ident)
else:
conc = self.extend(nart, root_plot, c_label, {LORE_SET_ELEMENT_ID: set(), OUTCOME_ELEMENT_ID: outc})
conc = self.extend(nart, root_plot, c_label, {LORE_SET_ELEMENT_ID: set(), OUTCOME_ELEMENT_ID: outc}, spident=ident)
if conc:
setattr(root_plot, "{}_WIN".format(ident),
QuestConclusionMethodWrapper(root_plot, outc.win_effect, True))
setattr(root_plot, "{}_LOSE".format(ident),
QuestConclusionMethodWrapper(root_plot, outc.loss_effect,
self.end_on_loss))

if not primary_conclusion:
primary_conclusion = conc
main_quest_line.append(conc)
for t in range(self.course_length):
tasks = 0
tries = 0
while tasks < self.course_length and tries < self.course_length * 5:
nu_parent = random.choice(main_quest_line)
nu_comp = self.extend(nart, nu_parent, self.task_ident, {LORE_SET_ELEMENT_ID: nu_parent.quest_record.needed_lore, OUTCOME_ELEMENT_ID: outc})
tries += 1
if nu_comp:
main_quest_line.append(nu_comp)
tasks += 1
else:
side_quest_line = [conc,]
tries = 0
while tries < self.course_length:
nu_parent = random.choice(side_quest_line)
nu_comp = self.extend(nart, nu_parent, self.task_ident, {LORE_SET_ELEMENT_ID: nu_parent.quest_record.needed_lore, OUTCOME_ELEMENT_ID: outc})
tries += 1
if nu_comp:
side_quest_line.append(nu_comp)

self.add_quest_lore_handler(root_plot, nart)

def _add_conclusion(self, root_plot, nart):
# The conclusion gets the lore of the provided outcome as its lore_menu
pass

def _add_complication(self, current_plot, nart):
# The complication gets the lore requirements of the current_plot as its lore_menu.
# Generally a complication locks one of the lore requirements and adds a lore requirement of its own.
pass

def _add_side_quest(self, current_plot, nart):
# A side quest gets the lore requirements of the current plot as its own lore requirements, then
# adds some extra lore to unlock this branch.
pass

def add_quest_lore_handler(self, root_plot, nart):
lore_set = set()

Expand Down Expand Up @@ -235,12 +249,12 @@ def check_quest_plot_activation(self, camp=None):
if camp:
camp.check_trigger('UPDATE')

def extend(self, nart, current_plot: plots.Plot, splabel, elements=None):
def extend(self, nart, current_plot: plots.Plot, splabel, elements=None, spident=None):
_elements = {QUEST_ELEMENT_ID: self}
if elements:
_elements.update(elements)
nuplot = current_plot.add_sub_plot(
nart, splabel, necessary=False, elements=_elements
nart, splabel, necessary=False, elements=_elements, ident=spident
)
if nuplot:
self.all_plots.append(nuplot)
Expand Down Expand Up @@ -280,11 +294,19 @@ class QuestRecord:
LOSS = -1
IN_PROGRESS = 0

def __init__(self, quest: Quest):
def __init__(self, quest: Quest, pstate: plots.PlotState):
self.quest = quest
self.completion = self.IN_PROGRESS
self.needed_lore = set()
self.lore_to_reveal = set()
my_lore = pstate.elements.get(LORE_SET_ELEMENT_ID, ())
if my_lore:
# Copy the priority lore from the set.
priority_lore = [l for l in my_lore if l.priority]
self.needed_lore.update(priority_lore)
else:
# Copy all the lore from the outcome.
self.needed_lore.update(pstate.elements.get(OUTCOME_ELEMENT_ID).lore)
self.started = False

def win_task(self, myplot: QuestPlot, camp):
Expand Down

0 comments on commit dc97366

Please sign in to comment.