mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Merge pull request #2880 from jjayers99/master
Adventure quests - initial implementation
This commit is contained in:
@@ -0,0 +1,156 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class ActionEdit extends FormPanel {
|
||||||
|
DialogData.ActionData currentData;
|
||||||
|
|
||||||
|
JTextField issueQuest = new JTextField();
|
||||||
|
JTextField mapFlagName = new JTextField();
|
||||||
|
JTextField questFlagName = new JTextField();
|
||||||
|
JTextField advanceMapFlag = new JTextField();
|
||||||
|
JTextField advanceQuestFlag = new JTextField();
|
||||||
|
JTextField battleWithActorID = new JTextField();
|
||||||
|
JTextField deleteMapObject = new JTextField();
|
||||||
|
JTextField setColorIdentity = new JTextField();
|
||||||
|
JSpinner addReputation = new JSpinner(new SpinnerNumberModel(0, -1000, 1000, 1));
|
||||||
|
JSpinner addLife = new JSpinner(new SpinnerNumberModel(0, -1000, 1000, 1));
|
||||||
|
JTextField POIReference = new JTextField();
|
||||||
|
JTextField removeItem = new JTextField();
|
||||||
|
JSpinner mapFlagValue = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
|
||||||
|
JSpinner questFlagValue = new JSpinner(new SpinnerNumberModel(0, 0, 1000, 1));
|
||||||
|
|
||||||
|
private boolean updating=false;
|
||||||
|
|
||||||
|
public ActionEdit()
|
||||||
|
{
|
||||||
|
|
||||||
|
//todo: add info pane to explain primary usage
|
||||||
|
|
||||||
|
add("Issue Quest:",issueQuest);
|
||||||
|
add("Set Map Flag Name:",mapFlagName);
|
||||||
|
add("Map Flag value to set:",mapFlagValue);
|
||||||
|
add("Set Quest Flag name:",questFlagName);
|
||||||
|
add("Quest Flag value to set:",questFlagValue);
|
||||||
|
|
||||||
|
add("Advance Map Flag name:",advanceMapFlag);
|
||||||
|
add("Advance Quest Flag name:",advanceQuestFlag);
|
||||||
|
add("Battle with actor ID:",battleWithActorID);
|
||||||
|
add("Delete map object:",deleteMapObject);
|
||||||
|
add("Set color identity:",setColorIdentity);
|
||||||
|
add("Add Reputation:",addReputation);
|
||||||
|
add("Add Life:",addLife);
|
||||||
|
add("POI Reference:",POIReference);
|
||||||
|
add("Remove Item:",removeItem);
|
||||||
|
|
||||||
|
issueQuest.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
mapFlagName.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
mapFlagValue.getModel().addChangeListener(e -> ActionEdit.this.updateAction());
|
||||||
|
questFlagName.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
questFlagValue.getModel().addChangeListener(e -> ActionEdit.this.updateAction());
|
||||||
|
advanceMapFlag.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
advanceQuestFlag.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
battleWithActorID.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
deleteMapObject.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
setColorIdentity.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
addLife.getModel().addChangeListener(e -> ActionEdit.this.updateAction());
|
||||||
|
addReputation.getModel().addChangeListener(e -> ActionEdit.this.updateAction());
|
||||||
|
POIReference.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
removeItem.getDocument().addDocumentListener(new DocumentChangeListener(ActionEdit.this::updateAction));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAction() {
|
||||||
|
if(updating)
|
||||||
|
return;
|
||||||
|
if (currentData == null)
|
||||||
|
currentData = new DialogData.ActionData();
|
||||||
|
|
||||||
|
DialogData.ActionData.QuestFlag mapFlag = new DialogData.ActionData.QuestFlag();
|
||||||
|
mapFlag.key = mapFlagName.getText();
|
||||||
|
mapFlag.val = (int)mapFlagValue.getModel().getValue();
|
||||||
|
currentData.setMapFlag= mapFlag;
|
||||||
|
|
||||||
|
DialogData.ActionData.QuestFlag questFlag = new DialogData.ActionData.QuestFlag();
|
||||||
|
questFlag.key = questFlagName.getText();
|
||||||
|
questFlag.val = (int)questFlagValue.getModel().getValue();
|
||||||
|
currentData.setQuestFlag= questFlag;
|
||||||
|
|
||||||
|
currentData.issueQuest = issueQuest.getText(); //This is currently a boolean effect, eventually needs arguments
|
||||||
|
currentData.advanceMapFlag= advanceMapFlag.getText();
|
||||||
|
currentData.advanceQuestFlag= advanceQuestFlag.getText();
|
||||||
|
currentData.battleWithActorID= Integer.parseInt(battleWithActorID.getText());
|
||||||
|
currentData.deleteMapObject= Integer.parseInt(deleteMapObject.getText());
|
||||||
|
currentData.setColorIdentity= setColorIdentity.getText();
|
||||||
|
currentData.addLife= (int) addLife.getModel().getValue();
|
||||||
|
currentData.addMapReputation= (int)addReputation.getModel().getValue();
|
||||||
|
currentData.POIReference= POIReference.getText();
|
||||||
|
currentData.removeItem= removeItem.getText();
|
||||||
|
|
||||||
|
//These need a dedicated effect editor
|
||||||
|
// JTextField setEffect = new JTextField();
|
||||||
|
// JTextField giveBlessing = new JTextField();
|
||||||
|
// currentData.giveBlessing= giveBlessing.getText();
|
||||||
|
// currentData.setEffect= setEffect.getText();
|
||||||
|
|
||||||
|
//These are valid pre-existing fields, but should be handled through the dedicated rewards editor
|
||||||
|
// currentData.addGold =;
|
||||||
|
// currentData.addItem=;
|
||||||
|
// currentData.grantRewards =;
|
||||||
|
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void addChangeListener(ChangeListener l) {
|
||||||
|
listenerList.add(ChangeListener.class, l);
|
||||||
|
}
|
||||||
|
public void setCurrentAction(DialogData.ActionData data)
|
||||||
|
{
|
||||||
|
currentData=data;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
setEnabled(currentData!=null);
|
||||||
|
if(currentData==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updating=true;
|
||||||
|
|
||||||
|
mapFlagName.setText(currentData.setMapFlag==null?"":currentData.setMapFlag.key);
|
||||||
|
mapFlagValue.getModel().setValue(currentData.setMapFlag==null?0:currentData.setMapFlag.val);
|
||||||
|
|
||||||
|
questFlagName.setText(currentData.setQuestFlag==null?"":currentData.setQuestFlag.key);
|
||||||
|
questFlagValue.getModel().setValue(currentData.setQuestFlag==null?0:currentData.setQuestFlag.val);
|
||||||
|
|
||||||
|
issueQuest.setText(currentData.issueQuest);
|
||||||
|
advanceMapFlag.setText(currentData.advanceMapFlag);
|
||||||
|
advanceQuestFlag.setText(currentData.advanceQuestFlag);
|
||||||
|
|
||||||
|
battleWithActorID.setText("" + currentData.battleWithActorID);
|
||||||
|
deleteMapObject.setText("" + currentData.deleteMapObject);
|
||||||
|
setColorIdentity.setText(currentData.setColorIdentity);
|
||||||
|
addLife.getModel().setValue(currentData.addLife);
|
||||||
|
addReputation.getModel().setValue(currentData.addMapReputation);
|
||||||
|
|
||||||
|
POIReference.setText(currentData.POIReference);
|
||||||
|
removeItem.setText(currentData.removeItem);
|
||||||
|
|
||||||
|
updating=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class ActionEditor extends JComponent{
|
||||||
|
DefaultListModel<DialogData.ActionData> model = new DefaultListModel<>();
|
||||||
|
JList<DialogData.ActionData> list = new JList<>(model);
|
||||||
|
JToolBar toolBar = new JToolBar("toolbar");
|
||||||
|
ActionEdit edit=new ActionEdit();
|
||||||
|
boolean updating;
|
||||||
|
|
||||||
|
|
||||||
|
public class RewardDataRenderer extends DefaultListCellRenderer {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean cellHasFocus) {
|
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
if(!(value instanceof DialogData.ActionData))
|
||||||
|
return label;
|
||||||
|
DialogData.ActionData action=(DialogData.ActionData) value;
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
// if(action.type==null||action.type.isEmpty())
|
||||||
|
builder.append("Action");
|
||||||
|
// else
|
||||||
|
// builder.append(action.type);
|
||||||
|
label.setText(builder.toString());
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void addButton(String name, ActionListener action)
|
||||||
|
{
|
||||||
|
JButton newButton=new JButton(name);
|
||||||
|
newButton.addActionListener(action);
|
||||||
|
toolBar.add(newButton);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ActionEditor()
|
||||||
|
{
|
||||||
|
|
||||||
|
list.setCellRenderer(new RewardDataRenderer());
|
||||||
|
list.addListSelectionListener(e -> ActionEditor.this.updateEdit());
|
||||||
|
addButton("add", e -> ActionEditor.this.addAction());
|
||||||
|
addButton("remove", e -> ActionEditor.this.remove());
|
||||||
|
addButton("copy", e -> ActionEditor.this.copy());
|
||||||
|
BorderLayout layout=new BorderLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
add(list, BorderLayout.LINE_START);
|
||||||
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
|
add(edit,BorderLayout.CENTER);
|
||||||
|
|
||||||
|
|
||||||
|
edit.addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
protected void emitChanged() {
|
||||||
|
if (updating)
|
||||||
|
return;
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void copy() {
|
||||||
|
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
DialogData.ActionData data=new DialogData.ActionData(model.get(selected));
|
||||||
|
model.add(model.size(),data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEdit() {
|
||||||
|
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
edit.setCurrentAction(model.get(selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addAction()
|
||||||
|
{
|
||||||
|
DialogData.ActionData data=new DialogData.ActionData();
|
||||||
|
model.add(model.size(),data);
|
||||||
|
}
|
||||||
|
void remove()
|
||||||
|
{
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
model.remove(selected);
|
||||||
|
}
|
||||||
|
public void setAction(DialogData.ActionData[] actions) {
|
||||||
|
|
||||||
|
model.clear();
|
||||||
|
if(actions==null)
|
||||||
|
return;
|
||||||
|
for (int i=0;i<actions.length;i++) {
|
||||||
|
if (actions[i].grantRewards.length > 0){
|
||||||
|
continue; //handled in separate editor and joined in on save, will get duplicated if it appears here
|
||||||
|
}
|
||||||
|
model.add(i,actions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData.ActionData[] getAction() {
|
||||||
|
|
||||||
|
DialogData.ActionData[] action= new DialogData.ActionData[model.getSize()];
|
||||||
|
for(int i=0;i<model.getSize();i++)
|
||||||
|
{
|
||||||
|
action[i]=model.get(i);
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear(){
|
||||||
|
updating = true;
|
||||||
|
model.clear();
|
||||||
|
updating = false;
|
||||||
|
}
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ public class BiomeEdit extends FormPanel {
|
|||||||
center.add("height:",height);
|
center.add("height:",height);
|
||||||
center.add("spriteNames:",spriteNames);
|
center.add("spriteNames:",spriteNames);
|
||||||
center.add("enemies:",enemies);
|
center.add("enemies:",enemies);
|
||||||
center.add("pointsOfInterest:",pointsOfInterest);
|
center.add("POITags:",pointsOfInterest);
|
||||||
center.add("color:",color);
|
center.add("color:",color);
|
||||||
center.add("collision:",collision);
|
center.add("collision:",collision);
|
||||||
center.add("terrain/structures:",new JLabel(""));
|
center.add("terrain/structures:",new JLabel(""));
|
||||||
|
|||||||
@@ -0,0 +1,155 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class DialogEdit extends FormPanel {
|
||||||
|
private boolean updating=false;
|
||||||
|
DialogData currentData;
|
||||||
|
|
||||||
|
public JTextField name=new JTextField(80);
|
||||||
|
public JTextField text=new JTextField(80);
|
||||||
|
public JTextField locname=new JTextField(80);
|
||||||
|
public JTextField loctext=new JTextField(80);
|
||||||
|
|
||||||
|
JPanel namePanel;
|
||||||
|
JPanel locNamePanel;
|
||||||
|
|
||||||
|
public JButton addNode = new JButton("Add node");
|
||||||
|
public JButton removeNode = new JButton("Remove node");
|
||||||
|
|
||||||
|
public DialogEdit()
|
||||||
|
{
|
||||||
|
FormPanel center=new FormPanel() { };
|
||||||
|
|
||||||
|
name.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
text.getDocument().addDocumentListener(new DocumentListener() {
|
||||||
|
@Override
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
if (!updating)
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
JPanel editData = new JPanel();
|
||||||
|
editData.setLayout(new BoxLayout(editData, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
namePanel = new JPanel();
|
||||||
|
namePanel.setLayout(new FlowLayout());
|
||||||
|
namePanel.add(new JLabel("Name:"));
|
||||||
|
namePanel.add(name);
|
||||||
|
editData.add(namePanel);
|
||||||
|
|
||||||
|
JPanel textPanel = new JPanel();
|
||||||
|
textPanel.setLayout(new FlowLayout());
|
||||||
|
textPanel.add(new JLabel("Text:"));
|
||||||
|
textPanel.add(text);
|
||||||
|
editData.add(textPanel);
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
buttonPanel.setLayout(new FlowLayout());
|
||||||
|
buttonPanel.add(addNode);
|
||||||
|
buttonPanel.add(removeNode);
|
||||||
|
editData.add(buttonPanel);
|
||||||
|
|
||||||
|
editData.add(new JLabel("localization tokens for translation"));
|
||||||
|
|
||||||
|
locNamePanel = new JPanel();
|
||||||
|
locNamePanel.setLayout(new FlowLayout());
|
||||||
|
locNamePanel.add(new JLabel("Name Token:"));
|
||||||
|
locNamePanel.add(locname);
|
||||||
|
|
||||||
|
|
||||||
|
JPanel locTextPanel = new JPanel();
|
||||||
|
locTextPanel.setLayout(new FlowLayout());
|
||||||
|
locTextPanel.add(new JLabel("Text Token:"));
|
||||||
|
locTextPanel.add(loctext);
|
||||||
|
|
||||||
|
editData.add(locNamePanel);
|
||||||
|
editData.add(locTextPanel);
|
||||||
|
center.add(editData);
|
||||||
|
|
||||||
|
add(center);
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(){
|
||||||
|
refresh(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(boolean onRootNode) {
|
||||||
|
setEnabled(currentData!=null);
|
||||||
|
if(currentData==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updating=true;
|
||||||
|
name.setText(currentData.name);
|
||||||
|
locname.setText(currentData.locname);
|
||||||
|
text.setText(currentData.text);
|
||||||
|
|
||||||
|
loctext.setText(currentData.loctext);
|
||||||
|
|
||||||
|
namePanel.setVisible(!onRootNode);
|
||||||
|
locNamePanel.setVisible(!onRootNode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
updating=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void emitChanged() {
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import com.google.common.collect.ObjectArrays;
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
import forge.adventure.data.RewardData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.DocumentEvent;
|
||||||
|
import javax.swing.event.DocumentListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class DialogEditor extends JComponent{
|
||||||
|
|
||||||
|
private boolean updating = false;
|
||||||
|
private java.util.List<DialogData> allNodes = new ArrayList<>();
|
||||||
|
|
||||||
|
public JTextArea text =new JTextArea("(Initial dialog text)", 3, 80);
|
||||||
|
public RewardsEditor rewardsEditor = new RewardsEditor();
|
||||||
|
public ActionEditor actionEditor = new ActionEditor();
|
||||||
|
public DialogOptionEditor optionEditor = new DialogOptionEditor();
|
||||||
|
public DialogTree navTree = new DialogTree();
|
||||||
|
|
||||||
|
public DialogEdit edit = new DialogEdit();
|
||||||
|
|
||||||
|
private DialogData root = new DialogData();
|
||||||
|
private DialogData current = new DialogData();
|
||||||
|
|
||||||
|
public DialogEditor(){
|
||||||
|
buildUI();
|
||||||
|
|
||||||
|
navTree.addSelectionListener(q -> loadNewNodeSelection());
|
||||||
|
edit.addChangeListener(q-> acceptEdits());
|
||||||
|
edit.addNode.addActionListener(q -> addNode());
|
||||||
|
edit.removeNode.addActionListener(q -> removeNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadData(DialogData rootDialogData){
|
||||||
|
updating = true;
|
||||||
|
if (rootDialogData == null)
|
||||||
|
{
|
||||||
|
rootDialogData = new DialogData();
|
||||||
|
}
|
||||||
|
root = rootDialogData;
|
||||||
|
navTree.loadDialog(rootDialogData);
|
||||||
|
text.setText(rootDialogData.text);
|
||||||
|
|
||||||
|
updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData getDialogData(){
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
|
JToolBar conditionsToolbar = new JToolBar("conditionsToolbar");
|
||||||
|
JToolBar actionsToolbar = new JToolBar("actionsToolbar");
|
||||||
|
JToolBar optionsToolbar = new JToolBar("optionsToolbar");
|
||||||
|
JToolBar tokensToolbar = new JToolBar("tokensToolbar");
|
||||||
|
|
||||||
|
JPanel conditionsPanel = new JPanel();
|
||||||
|
JPanel actionsPanel = new JPanel();
|
||||||
|
JPanel optionsPanel = new JPanel();
|
||||||
|
JPanel rewardsPanel = new JPanel();
|
||||||
|
JPanel tokensPanel = new JPanel();
|
||||||
|
|
||||||
|
class QuestTextDocumentListener implements DocumentListener {
|
||||||
|
public void changedUpdate(DocumentEvent e) {
|
||||||
|
root.text = text.getText();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
public void removeUpdate(DocumentEvent e) {
|
||||||
|
root.text = text.getText();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
public void insertUpdate(DocumentEvent e) {
|
||||||
|
root.text = text.getText();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildUI(){
|
||||||
|
buildTabs();
|
||||||
|
BorderLayout layout=new BorderLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
JPanel textArea = new JPanel();
|
||||||
|
textArea.setLayout(new FlowLayout());
|
||||||
|
textArea.add(new JLabel("Dialog Start"));
|
||||||
|
textArea.add(text);
|
||||||
|
text.getDocument().addDocumentListener(new QuestTextDocumentListener());
|
||||||
|
|
||||||
|
JSplitPane splitPane = new JSplitPane();
|
||||||
|
splitPane.setLeftComponent(navTree);
|
||||||
|
splitPane.setRightComponent(tabs);
|
||||||
|
splitPane.setResizeWeight(0.2);
|
||||||
|
splitPane.setDividerLocation(.2);
|
||||||
|
|
||||||
|
add(textArea, BorderLayout.NORTH);
|
||||||
|
add(splitPane, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadNewNodeSelection(){
|
||||||
|
updating = true;
|
||||||
|
current = navTree.getSelectedData();
|
||||||
|
edit.currentData = navTree.getSelectedData();
|
||||||
|
edit.refresh(root.equals(current));
|
||||||
|
rewardsEditor.clear();
|
||||||
|
actionEditor.clear();
|
||||||
|
if (navTree.getSelectedData() != null) {
|
||||||
|
for (DialogData.ActionData action : navTree.getSelectedData().action) {
|
||||||
|
if (action.grantRewards != null && action.grantRewards.length > 0)
|
||||||
|
rewardsEditor.setRewards(action.grantRewards);
|
||||||
|
}
|
||||||
|
actionEditor.setAction(navTree.getSelectedData().action);
|
||||||
|
}
|
||||||
|
updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acceptEdits(){
|
||||||
|
if (current == null)
|
||||||
|
return;
|
||||||
|
current.name = edit.name.getText();
|
||||||
|
current.text = edit.text.getText();
|
||||||
|
current.locname = edit.locname.getText();
|
||||||
|
current.loctext = edit.loctext.getText();
|
||||||
|
root.text = text.getText();
|
||||||
|
|
||||||
|
DialogData.ActionData[] action = actionEditor.getAction();
|
||||||
|
|
||||||
|
ArrayList<DialogData.ActionData> actionsList = new ArrayList<>(Arrays.stream(action).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
RewardData[] rewards= rewardsEditor.getRewards();
|
||||||
|
if (rewards.length > 0)
|
||||||
|
{
|
||||||
|
DialogData.ActionData rewardAction = new DialogData.ActionData();
|
||||||
|
rewardAction.grantRewards = rewards;
|
||||||
|
actionsList.add(rewardAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
current.action = actionsList.toArray(current.action);
|
||||||
|
|
||||||
|
navTree.replaceCurrent();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNode(){
|
||||||
|
DialogData newNode = new DialogData();
|
||||||
|
newNode.name = "NewResponse";
|
||||||
|
DialogData parent = navTree.getSelectedData()!=null?navTree.getSelectedData():root;
|
||||||
|
parent.options = ObjectArrays.concat(parent.options, newNode);
|
||||||
|
navTree.loadDialog(root);
|
||||||
|
navTree.setSelectedData(newNode);
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
public void removeNode(){
|
||||||
|
if (navTree.getSelectedData() == null)
|
||||||
|
return;
|
||||||
|
navTree.removeSelectedData();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildTabs(){
|
||||||
|
buildToolBars();
|
||||||
|
|
||||||
|
actionsPanel.add(actionsToolbar);
|
||||||
|
actionsPanel.add(actionEditor);
|
||||||
|
optionsPanel.add(edit);
|
||||||
|
rewardsPanel.add(rewardsEditor);
|
||||||
|
rewardsEditor.addChangeListener(e -> DialogEditor.this.acceptEdits());
|
||||||
|
actionEditor.addChangeListener(e -> DialogEditor.this.acceptEdits());
|
||||||
|
tokensPanel.add(tokensToolbar);
|
||||||
|
tokensPanel.add(new JLabel("Insert token editor here"));
|
||||||
|
|
||||||
|
tabs.addTab("Options", optionsPanel);
|
||||||
|
tabs.addTab("Conditions", conditionsPanel);
|
||||||
|
tabs.addTab("Actions", actionsPanel);
|
||||||
|
tabs.addTab("Rewards", rewardsPanel);
|
||||||
|
tabs.addTab("Tokens",tokensPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildToolBars(){
|
||||||
|
conditionsToolbar.setFloatable(false);
|
||||||
|
actionsToolbar.setFloatable(false);
|
||||||
|
optionsToolbar.setFloatable(false);
|
||||||
|
|
||||||
|
JButton addOption = new JButton("Add Option");
|
||||||
|
addOption.addActionListener(e -> DialogEditor.this.addOption());
|
||||||
|
optionsToolbar.add(addOption);
|
||||||
|
|
||||||
|
JButton copyOption = new JButton("Copy Selected");
|
||||||
|
copyOption.addActionListener(e -> DialogEditor.this.copyOption());
|
||||||
|
optionsToolbar.add(copyOption);
|
||||||
|
|
||||||
|
JButton removeOption = new JButton("Remove Selected");
|
||||||
|
removeOption.addActionListener(e -> DialogEditor.this.removeOption());
|
||||||
|
optionsToolbar.add(removeOption);
|
||||||
|
|
||||||
|
}
|
||||||
|
public void addOption(){
|
||||||
|
optionEditor.addOption();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyOption(){
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOption(){
|
||||||
|
int selected=optionEditor.list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
optionEditor.model.remove(selected);
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void emitChanged() {
|
||||||
|
if (updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class DialogOptionEdit extends FormPanel {
|
||||||
|
DialogData currentData;
|
||||||
|
|
||||||
|
JLabel nameLabel = new JLabel("Name (Player dialog / action)");
|
||||||
|
JLabel textLabel = new JLabel("Text (Game response to Name - Leave blank to end dialog)");
|
||||||
|
JTextArea text =new JTextArea(3,80);
|
||||||
|
JTextArea name =new JTextArea(3,80);
|
||||||
|
JButton add = new JButton();
|
||||||
|
JButton load = new JButton();
|
||||||
|
|
||||||
|
private boolean updating=false;
|
||||||
|
|
||||||
|
public DialogOptionEdit()
|
||||||
|
{
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
|
||||||
|
JPanel upper = new JPanel();
|
||||||
|
upper.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
upper.add(nameLabel, BorderLayout.NORTH);
|
||||||
|
upper.add(name, BorderLayout.CENTER);
|
||||||
|
add(upper);
|
||||||
|
|
||||||
|
JPanel middle = new JPanel();
|
||||||
|
middle.setLayout(new BorderLayout());
|
||||||
|
middle.add(textLabel, BorderLayout.NORTH);
|
||||||
|
middle.add(text, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
add(middle);
|
||||||
|
|
||||||
|
name.getDocument().addDocumentListener(new DocumentChangeListener(() -> DialogOptionEdit.this.updateDialog()));
|
||||||
|
text.getDocument().addDocumentListener(new DocumentChangeListener(() -> DialogOptionEdit.this.updateDialog()));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDialog() {
|
||||||
|
if(currentData==null||updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentData.text = text.getText().trim();
|
||||||
|
currentData.name = name.getText().trim();
|
||||||
|
|
||||||
|
//currentData.condition = conditionEditor.getConditions();
|
||||||
|
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public void addChangeListener(ChangeListener l) {
|
||||||
|
listenerList.add(ChangeListener.class, l);
|
||||||
|
}
|
||||||
|
public void setCurrentOption(DialogData data)
|
||||||
|
{
|
||||||
|
currentData=data;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
setEnabled(currentData!=null);
|
||||||
|
updating=true;
|
||||||
|
|
||||||
|
text.setText(currentData.text!=null?currentData.text:"");
|
||||||
|
name.setText(currentData.name!=null?currentData.name:"");
|
||||||
|
|
||||||
|
updating=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class DialogOptionEditor extends JComponent{
|
||||||
|
DefaultListModel<DialogData> model = new DefaultListModel<>();
|
||||||
|
JList<DialogData> list = new JList<>(model);
|
||||||
|
JToolBar toolBar = new JToolBar("toolbar");
|
||||||
|
DialogOptionEdit edit=new DialogOptionEdit();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class DialogDataRenderer extends DefaultListCellRenderer {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean cellHasFocus) {
|
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
if(!(value instanceof DialogData))
|
||||||
|
return label;
|
||||||
|
DialogData dialog=(DialogData) value;
|
||||||
|
StringBuilder builder=new StringBuilder();
|
||||||
|
if(dialog.name==null||dialog.name.isEmpty())
|
||||||
|
builder.append("[[Blank Option]]");
|
||||||
|
else
|
||||||
|
builder.append(dialog.name, 0, Math.min(dialog.name.length(), 25));
|
||||||
|
label.setText(builder.toString());
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void addButton(String name, ActionListener action)
|
||||||
|
{
|
||||||
|
JButton newButton=new JButton(name);
|
||||||
|
newButton.addActionListener(action);
|
||||||
|
toolBar.add(newButton);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogOptionEditor()
|
||||||
|
{
|
||||||
|
|
||||||
|
list.setCellRenderer(new DialogDataRenderer());
|
||||||
|
list.addListSelectionListener(e -> DialogOptionEditor.this.updateEdit());
|
||||||
|
addButton("add", e -> DialogOptionEditor.this.addOption());
|
||||||
|
addButton("remove", e -> DialogOptionEditor.this.remove());
|
||||||
|
addButton("copy", e -> DialogOptionEditor.this.copy());
|
||||||
|
BorderLayout layout=new BorderLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
add(list, BorderLayout.LINE_START);
|
||||||
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
|
add(edit,BorderLayout.CENTER);
|
||||||
|
edit.setVisible(false);
|
||||||
|
|
||||||
|
edit.addChangeListener(e -> emitChanged());
|
||||||
|
}
|
||||||
|
protected void emitChanged() {
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void copy() {
|
||||||
|
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
DialogData data=new DialogData(model.get(selected));
|
||||||
|
model.add(model.size(),data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEdit() {
|
||||||
|
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
edit.setCurrentOption(new DialogData());
|
||||||
|
else
|
||||||
|
edit.setCurrentOption(model.get(selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addOption()
|
||||||
|
{
|
||||||
|
DialogData data=new DialogData();
|
||||||
|
model.add(model.size(),data);
|
||||||
|
edit.setVisible(true);
|
||||||
|
list.setSelectedIndex(model.size() - 1);
|
||||||
|
}
|
||||||
|
void remove()
|
||||||
|
{
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
model.remove(selected);
|
||||||
|
edit.setVisible(model.size() > 0);
|
||||||
|
}
|
||||||
|
public void setOptions(DialogData[] options) {
|
||||||
|
model.clear();
|
||||||
|
if(options==null || options.length == 0)
|
||||||
|
options = new DialogData[0];
|
||||||
|
for (int i=0;i<options.length;i++) {
|
||||||
|
model.add(i,options[i]);
|
||||||
|
}
|
||||||
|
if (model.size() > 0)
|
||||||
|
{
|
||||||
|
edit.setVisible(true);
|
||||||
|
list.setSelectedIndex(0);
|
||||||
|
updateEdit();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
edit.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData[] getOptions() {
|
||||||
|
DialogData[] options= new DialogData[model.getSize()];
|
||||||
|
for(int i=0;i<model.getSize();i++)
|
||||||
|
{
|
||||||
|
options[i]=model.get(i);
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.DialogData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import javax.swing.tree.TreeSelectionModel;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DialogTree extends JPanel {
|
||||||
|
|
||||||
|
// private DefaultMutableTreeNode rootNode;
|
||||||
|
private JTree dialogTree;
|
||||||
|
private JScrollPane scrollPane;
|
||||||
|
|
||||||
|
|
||||||
|
public DialogTree(){
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
// Create the JTree component
|
||||||
|
dialogTree = new JTree();
|
||||||
|
dialogTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
|
||||||
|
addSelectionListener();
|
||||||
|
// Create a scroll pane to contain the JTree
|
||||||
|
scrollPane = new JScrollPane(dialogTree);
|
||||||
|
// Add the scroll pane to the panel
|
||||||
|
add(scrollPane, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadDialog(DialogData dialogData){
|
||||||
|
// rootNode = buildBranches(dialogData);
|
||||||
|
// ((DefaultTreeModel)dialogTree.getModel()).setRoot(rootNode);
|
||||||
|
((DefaultTreeModel)dialogTree.getModel()).setRoot(buildBranches(dialogData));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultMutableTreeNode buildBranches(DialogData dialogData)
|
||||||
|
{
|
||||||
|
DefaultMutableTreeNode node = new DefaultMutableTreeNode(dialogData);
|
||||||
|
for (DialogData option : dialogData.options){
|
||||||
|
node.add(buildBranches(option));
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<TreeSelectionListener> selectionListeners = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addSelectionListener(){
|
||||||
|
//subscribe to valueChanged, change to that object in edit pane
|
||||||
|
dialogTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(TreeSelectionEvent e) {
|
||||||
|
emitChanged(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSelectionListener(final TreeSelectionListener listener) {
|
||||||
|
selectionListeners.remove(listener); //ensure listener not added multiple times
|
||||||
|
selectionListeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void emitChanged(TreeSelectionEvent evt) {
|
||||||
|
if (selectionListeners != null && selectionListeners.size() > 0) {
|
||||||
|
for (TreeSelectionListener listener : selectionListeners) {
|
||||||
|
listener.valueChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceCurrent(){
|
||||||
|
if (dialogTree.getSelectionPath() == null || dialogTree.getSelectionPath().getLastPathComponent() == null)
|
||||||
|
return;
|
||||||
|
dialogTree.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData getSelectedData() {
|
||||||
|
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) dialogTree.getLastSelectedPathComponent();
|
||||||
|
if (selectedNode != null) {
|
||||||
|
return (DialogData) selectedNode.getUserObject();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSelectedData() {
|
||||||
|
//Todo: Enhance this to not collapse any nodes (after setSelectedData other paths are still collapsed)
|
||||||
|
DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) dialogTree.getLastSelectedPathComponent();
|
||||||
|
|
||||||
|
DialogData parentData = (DialogData) ((DefaultMutableTreeNode)selectedNode.getParent()).getUserObject();
|
||||||
|
((DefaultTreeModel) dialogTree.getModel()).removeNodeFromParent(selectedNode);
|
||||||
|
((DefaultTreeModel) dialogTree.getModel()).reload();
|
||||||
|
|
||||||
|
setSelectedData(parentData);
|
||||||
|
}
|
||||||
|
public void setSelectedData(DialogData data) {
|
||||||
|
// Find the node with the given data object and select it in the tree
|
||||||
|
DefaultMutableTreeNode node = findNode((DefaultMutableTreeNode)dialogTree.getModel().getRoot(), data);
|
||||||
|
if (node != null) {
|
||||||
|
dialogTree.setSelectionPath(new TreePath(node.getPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultMutableTreeNode findNode(DefaultMutableTreeNode parent, DialogData data) {
|
||||||
|
// Search for the node with the given data object in the subtree rooted at the parent node
|
||||||
|
if (parent.getUserObject() == data) {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < parent.getChildCount(); i++) {
|
||||||
|
DefaultMutableTreeNode child = (DefaultMutableTreeNode) parent.getChildAt(i);
|
||||||
|
DefaultMutableTreeNode result = findNode(child, data);
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,14 +35,18 @@ public class EditorMainWindow extends JFrame {
|
|||||||
newButton.addActionListener(e -> EventQueue.invokeLater(() ->new ParticleEditor()));
|
newButton.addActionListener(e -> EventQueue.invokeLater(() ->new ParticleEditor()));
|
||||||
toolBar.add(newButton);
|
toolBar.add(newButton);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
add(toolBar, BorderLayout.NORTH);
|
add(toolBar, BorderLayout.NORTH);
|
||||||
add(tabs, BorderLayout.CENTER);
|
add(tabs, BorderLayout.CENTER);
|
||||||
tabs.addTab("World",worldEditor);
|
tabs.addTab("World",worldEditor);
|
||||||
tabs.addTab("POI",new PointOfInterestEditor());
|
tabs.addTab("POI",new PointOfInterestEditor());
|
||||||
tabs.addTab("Items",new ItemsEditor());
|
tabs.addTab("Items",new ItemsEditor());
|
||||||
tabs.addTab("Enemies",new EnemyEditor());
|
tabs.addTab("Enemies",new EnemyEditor());
|
||||||
|
tabs.addTab("Quests",new QuestEditor());
|
||||||
|
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
setSize(800,600);
|
setSize(800,600);
|
||||||
|
GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow( this );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ package forge.adventure.editor;
|
|||||||
import forge.adventure.data.EnemyData;
|
import forge.adventure.data.EnemyData;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListDataEvent;
|
||||||
|
import javax.swing.event.ListDataListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Editor class to edit configuration, maybe moved or removed
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
@@ -10,6 +16,7 @@ import javax.swing.*;
|
|||||||
public class EnemyEdit extends FormPanel {
|
public class EnemyEdit extends FormPanel {
|
||||||
EnemyData currentData;
|
EnemyData currentData;
|
||||||
JTextField nameField=new JTextField();
|
JTextField nameField=new JTextField();
|
||||||
|
JTextField nameOverride=new JTextField();
|
||||||
JTextField colorField=new JTextField();
|
JTextField colorField=new JTextField();
|
||||||
JTextField ai=new JTextField();
|
JTextField ai=new JTextField();
|
||||||
JCheckBox flying=new JCheckBox();
|
JCheckBox flying=new JCheckBox();
|
||||||
@@ -24,51 +31,235 @@ public class EnemyEdit extends FormPanel {
|
|||||||
JTextField equipment=new JTextField();
|
JTextField equipment=new JTextField();
|
||||||
RewardsEditor rewards=new RewardsEditor();
|
RewardsEditor rewards=new RewardsEditor();
|
||||||
SwingAtlasPreview preview=new SwingAtlasPreview();
|
SwingAtlasPreview preview=new SwingAtlasPreview();
|
||||||
|
JTextField manualEntry = new JTextField(20);
|
||||||
private boolean updating=false;
|
private boolean updating=false;
|
||||||
|
|
||||||
|
DefaultListModel<String> existingModel = new DefaultListModel<>();
|
||||||
|
DefaultListModel<String> enemyModel = new DefaultListModel<>();
|
||||||
|
JList<String> existingTags;
|
||||||
|
JList<String> enemyTags;
|
||||||
|
|
||||||
public EnemyEdit()
|
public EnemyEdit()
|
||||||
{
|
{
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
FormPanel top=new FormPanel() { };
|
||||||
|
add(top, BorderLayout.NORTH);
|
||||||
|
|
||||||
FormPanel center=new FormPanel() { };
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
|
add(tabs, BorderLayout.CENTER);
|
||||||
|
FormPanel basicInfo=new FormPanel() { };
|
||||||
|
tabs.addTab("Basic Info", basicInfo);
|
||||||
|
|
||||||
center.add("Name:",nameField);
|
top.add("Name:",nameField);
|
||||||
center.add("Life:",lifeFiled);
|
top.add("Display Name:", nameOverride);
|
||||||
center.add("Spawn rate:",spawnRate);
|
|
||||||
center.add("Difficulty:",difficulty);
|
|
||||||
center.add("Speed:",speed);
|
|
||||||
center.add("Deck:",deck);
|
|
||||||
center.add("Sprite:",atlas);
|
|
||||||
center.add("Equipment:",equipment);
|
|
||||||
center.add("Colors:",colorField);
|
|
||||||
|
|
||||||
center.add("ai:",ai);
|
basicInfo.add("Life:",lifeFiled);
|
||||||
center.add("flying:",flying);
|
basicInfo.add("Spawn rate:",spawnRate);
|
||||||
center.add("boss:",boss);
|
basicInfo.add("Difficulty:",difficulty);
|
||||||
|
basicInfo.add("Speed:",speed);
|
||||||
|
basicInfo.add("Deck:",deck);
|
||||||
|
basicInfo.add("Equipment:",equipment);
|
||||||
|
basicInfo.add("Colors:",colorField);
|
||||||
|
|
||||||
|
basicInfo.add("ai:",ai);
|
||||||
|
basicInfo.add("flying:",flying);
|
||||||
|
basicInfo.add("boss:",boss);
|
||||||
|
|
||||||
|
JPanel visual = new JPanel();
|
||||||
|
|
||||||
|
visual.add("Sprite:",atlas);
|
||||||
|
visual.add(preview);
|
||||||
|
|
||||||
|
JPanel tags = new JPanel();
|
||||||
|
existingTags = new JList<>();
|
||||||
|
|
||||||
|
|
||||||
add(preview);
|
existingTags.getInputMap(JList.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
|
||||||
add(center);
|
KeyStroke.getKeyStroke("ENTER"), "addSelected");
|
||||||
add(rewards);
|
existingTags.getActionMap().put("addSelected", new AbstractAction() {
|
||||||
|
|
||||||
equipment.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
@Override
|
||||||
atlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
public void actionPerformed(ActionEvent e) {
|
||||||
colorField.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
addSelected();
|
||||||
ai.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
|
||||||
|
int index = existingTags.getSelectedIndex();
|
||||||
|
|
||||||
|
String selectedItem = existingTags.getSelectedValue();
|
||||||
|
|
||||||
|
if (selectedItem != null) {
|
||||||
|
enemyModel.addElement(selectedItem);
|
||||||
|
existingTags.grabFocus();
|
||||||
|
existingTags.setSelectedIndex(index<existingModel.size()?index:index-1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
existingModel = QuestController.getInstance().getEnemyTags(true);
|
||||||
|
existingTags.setModel(existingModel);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enemyTags = new JList<>();
|
||||||
|
enemyModel = new DefaultListModel<>();
|
||||||
|
enemyTags.setModel(enemyModel);
|
||||||
|
|
||||||
|
enemyTags.getModel().addListDataListener(new ListDataListener() {
|
||||||
|
@Override
|
||||||
|
public void intervalAdded(ListDataEvent e) {
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void intervalRemoved(ListDataEvent e) {
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contentsChanged(ListDataEvent e) {
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton select = new JButton("Select");
|
||||||
|
select.addActionListener(q -> addSelected());
|
||||||
|
JButton add = new JButton("Manual Add");
|
||||||
|
add.addActionListener(q -> manualAdd(enemyModel));
|
||||||
|
JButton remove = new JButton("Remove Item");
|
||||||
|
remove.addActionListener(q -> removeSelected());
|
||||||
|
|
||||||
|
tags.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel left = new JPanel();
|
||||||
|
left.setLayout(new BorderLayout());
|
||||||
|
left.add(new JLabel("Tags already in use"), BorderLayout.NORTH);
|
||||||
|
JScrollPane listScroller = new JScrollPane(existingTags);
|
||||||
|
listScroller.setMinimumSize(new Dimension(400, 800));
|
||||||
|
left.add(listScroller, BorderLayout.CENTER);
|
||||||
|
tags.add(left, BorderLayout.WEST);
|
||||||
|
|
||||||
|
FormPanel tagEdit = new FormPanel();
|
||||||
|
tagEdit.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
FormPanel mappedTags = new FormPanel();
|
||||||
|
mappedTags.setLayout(new BorderLayout());
|
||||||
|
mappedTags.add(new JLabel("Tags Mapped to this object"), BorderLayout.NORTH);
|
||||||
|
JScrollPane listScroller2 = new JScrollPane(enemyTags);
|
||||||
|
listScroller2.setMinimumSize(new Dimension(400, 800));
|
||||||
|
mappedTags.add(listScroller2, BorderLayout.CENTER);
|
||||||
|
tagEdit.add(mappedTags,BorderLayout.EAST);
|
||||||
|
|
||||||
|
JPanel controlPanel = new JPanel();
|
||||||
|
|
||||||
|
controlPanel.add(select);
|
||||||
|
controlPanel.add(add);
|
||||||
|
controlPanel.add(manualEntry);
|
||||||
|
|
||||||
|
manualEntry.getInputMap(JList.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
|
||||||
|
KeyStroke.getKeyStroke("ENTER"), "addTyped");
|
||||||
|
manualEntry.getActionMap().put("addTyped", new AbstractAction() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
if (!manualEntry.getText().trim().isEmpty()) {
|
||||||
|
manualAdd(enemyModel);
|
||||||
|
manualEntry.grabFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
controlPanel.add(remove);
|
||||||
|
tagEdit.add(controlPanel, BorderLayout.CENTER);
|
||||||
|
tags.add(tagEdit,BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JTextArea right1 = new JTextArea("This is really just to pad some space\n" +
|
||||||
|
"but also to explain the use of tags.\n" +
|
||||||
|
"Rather than adding 100's of object names\n" +
|
||||||
|
"to every quest definition, instead we will\n"+
|
||||||
|
"categorize enemies and points of interest with\n"+
|
||||||
|
"tags and reference those categories in quests");
|
||||||
|
right1.setEnabled(false);
|
||||||
|
tags.add(right1, BorderLayout.EAST);
|
||||||
|
tabs.addTab("Sprite", visual);
|
||||||
|
tabs.addTab("Rewards", rewards);
|
||||||
|
tabs.addTab("Quest Tags", tags);
|
||||||
|
|
||||||
|
|
||||||
|
equipment.getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
|
atlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
|
colorField.getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
|
ai.getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
flying.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
flying.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
boss.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
boss.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
ignoreDungeonEffect.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
ignoreDungeonEffect.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
nameField.getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
nameField.getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
deck.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> EnemyEdit.this.updateEnemy()));
|
nameOverride.getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
|
deck.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(EnemyEdit.this::updateEnemy));
|
||||||
lifeFiled.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
lifeFiled.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
speed.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
speed.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
difficulty.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
difficulty.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
spawnRate.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
spawnRate.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
rewards.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
rewards.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
lifeFiled.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
lifeFiled.addChangeListener(e -> EnemyEdit.this.updateEnemy());
|
||||||
|
enemyModel.addListDataListener(new ListDataListener() {
|
||||||
|
@Override
|
||||||
|
public void intervalAdded(ListDataEvent e) {
|
||||||
|
EnemyEdit.this.updateEnemy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void intervalRemoved(ListDataEvent e) {
|
||||||
|
EnemyEdit.this.updateEnemy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contentsChanged(ListDataEvent e) {
|
||||||
|
EnemyEdit.this.updateEnemy();
|
||||||
|
}
|
||||||
|
});
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateEnemy() {
|
|
||||||
|
private void doUpdate(){
|
||||||
|
EnemyEdit.this.updateEnemy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSelected(){
|
||||||
|
if (existingTags.getSelectedIndex()>-1)
|
||||||
|
enemyModel.addElement(existingTags.getModel().getElementAt(existingTags.getSelectedIndex()));
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeSelected(){
|
||||||
|
if (enemyTags.getSelectedIndex()>-1)
|
||||||
|
enemyModel.remove(enemyTags.getSelectedIndex());
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterExisting(DefaultListModel<String> filter){
|
||||||
|
DefaultListModel<String> toReturn = new DefaultListModel<>();
|
||||||
|
for (Enumeration<String> e = QuestController.getInstance().getEnemyTags(true).elements(); e.hasMoreElements();){
|
||||||
|
String toTest = e.nextElement();
|
||||||
|
if (toTest != null & !filter.contains(toTest)){
|
||||||
|
toReturn.addElement(toTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
existingTags.setModel(toReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void manualAdd(DefaultListModel<String> model){
|
||||||
|
if (!manualEntry.getText().trim().isEmpty())
|
||||||
|
model.addElement(manualEntry.getText().trim());
|
||||||
|
manualEntry.setText("");
|
||||||
|
doUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEnemy() {
|
||||||
if(currentData==null||updating)
|
if(currentData==null||updating)
|
||||||
return;
|
return;
|
||||||
currentData.name=nameField.getText();
|
currentData.name=nameField.getText();
|
||||||
@@ -88,6 +279,15 @@ public class EnemyEdit extends FormPanel {
|
|||||||
currentData.deck= deck.getEdit().getText().split(",");
|
currentData.deck= deck.getEdit().getText().split(",");
|
||||||
currentData.rewards= rewards.getRewards();
|
currentData.rewards= rewards.getRewards();
|
||||||
preview.setSpritePath(currentData.sprite);
|
preview.setSpritePath(currentData.sprite);
|
||||||
|
|
||||||
|
ArrayList<String> tags = new ArrayList<>();
|
||||||
|
for (Enumeration<String> e = enemyModel.elements(); e.hasMoreElements();){
|
||||||
|
tags.add(e.nextElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentData.questTags = tags.toArray(currentData.questTags);
|
||||||
|
QuestController.getInstance().refresh();
|
||||||
|
filterExisting(enemyModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentEnemy(EnemyData data)
|
public void setCurrentEnemy(EnemyData data)
|
||||||
@@ -120,6 +320,12 @@ public class EnemyEdit extends FormPanel {
|
|||||||
difficulty.setValue(new Float(currentData.difficulty).doubleValue());
|
difficulty.setValue(new Float(currentData.difficulty).doubleValue());
|
||||||
rewards.setRewards(currentData.rewards);
|
rewards.setRewards(currentData.rewards);
|
||||||
preview.setSpritePath(currentData.sprite);
|
preview.setSpritePath(currentData.sprite);
|
||||||
|
enemyModel.clear();
|
||||||
|
for(String val : currentData.questTags) {
|
||||||
|
if (val != null)
|
||||||
|
enemyModel.addElement(val);
|
||||||
|
}
|
||||||
|
filterExisting(enemyModel);
|
||||||
updating=false;
|
updating=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,10 +9,7 @@ import forge.adventure.util.Config;
|
|||||||
import forge.adventure.util.Paths;
|
import forge.adventure.util.Paths;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
|
||||||
import javax.swing.event.ListSelectionListener;
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,45 +58,19 @@ public class EnemyEditor extends JComponent {
|
|||||||
{
|
{
|
||||||
|
|
||||||
list.setCellRenderer(new EnemyDataRenderer());
|
list.setCellRenderer(new EnemyDataRenderer());
|
||||||
list.addListSelectionListener(new ListSelectionListener() {
|
list.addListSelectionListener(e -> EnemyEditor.this.updateEdit());
|
||||||
@Override
|
addButton("add", e -> EnemyEditor.this.addEnemy());
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
addButton("remove", e -> EnemyEditor.this.remove());
|
||||||
EnemyEditor.this.updateEdit();
|
addButton("copy", e -> EnemyEditor.this.copy());
|
||||||
}
|
addButton("load", e -> {
|
||||||
});
|
EnemyEditor.this.load();
|
||||||
addButton("add", new ActionListener() {
|
QuestController.getInstance().load();
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
EnemyEditor.this.addEnemy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addButton("remove", new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
EnemyEditor.this.remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addButton("copy", new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
EnemyEditor.this.copy();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addButton("load", new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
EnemyEditor.this.load();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
addButton("save", new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
EnemyEditor.this.save();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
addButton("save", e -> EnemyEditor.this.save());
|
||||||
BorderLayout layout=new BorderLayout();
|
BorderLayout layout=new BorderLayout();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
add(new JScrollPane(list), BorderLayout.LINE_START);
|
add(new JScrollPane(list), BorderLayout.LINE_START);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
add(toolBar, BorderLayout.PAGE_START);
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
add(edit,BorderLayout.CENTER);
|
add(edit,BorderLayout.CENTER);
|
||||||
load();
|
load();
|
||||||
@@ -118,6 +89,7 @@ public class EnemyEditor extends JComponent {
|
|||||||
if(selected<0)
|
if(selected<0)
|
||||||
return;
|
return;
|
||||||
edit.setCurrentEnemy(model.get(selected));
|
edit.setCurrentEnemy(model.get(selected));
|
||||||
|
edit.updateEnemy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void save()
|
void save()
|
||||||
@@ -138,8 +110,7 @@ public class EnemyEditor extends JComponent {
|
|||||||
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
|
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
|
||||||
if (handle.exists())
|
if (handle.exists())
|
||||||
{
|
{
|
||||||
Array readEnemies=json.fromJson(Array.class, EnemyData.class, handle);
|
allEnemies = json.fromJson(Array.class, EnemyData.class, handle);
|
||||||
allEnemies = readEnemies;
|
|
||||||
}
|
}
|
||||||
for (int i=0;i<allEnemies.size;i++) {
|
for (int i=0;i<allEnemies.size;i++) {
|
||||||
model.add(i,allEnemies.get(i));
|
model.add(i,allEnemies.get(i));
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ public class ItemsEditor extends JComponent {
|
|||||||
BorderLayout layout=new BorderLayout();
|
BorderLayout layout=new BorderLayout();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
add(new JScrollPane(list), BorderLayout.LINE_START);
|
add(new JScrollPane(list), BorderLayout.LINE_START);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
add(toolBar, BorderLayout.PAGE_START);
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
add(edit,BorderLayout.CENTER);
|
add(edit,BorderLayout.CENTER);
|
||||||
load();
|
load();
|
||||||
@@ -105,8 +106,7 @@ public class ItemsEditor extends JComponent {
|
|||||||
FileHandle handle = Config.instance().getFile(Paths.ITEMS);
|
FileHandle handle = Config.instance().getFile(Paths.ITEMS);
|
||||||
if (handle.exists())
|
if (handle.exists())
|
||||||
{
|
{
|
||||||
Array readEnemies=json.fromJson(Array.class, ItemData.class, handle);
|
allEnemies =json.fromJson(Array.class, ItemData.class, handle);
|
||||||
allEnemies = readEnemies;
|
|
||||||
}
|
}
|
||||||
for (int i=0;i<allEnemies.size;i++) {
|
for (int i=0;i<allEnemies.size;i++) {
|
||||||
model.add(i,allEnemies.get(i));
|
model.add(i,allEnemies.get(i));
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ package forge.adventure.editor;
|
|||||||
import forge.adventure.data.PointOfInterestData;
|
import forge.adventure.data.PointOfInterestData;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ListDataEvent;
|
||||||
|
import javax.swing.event.ListDataListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
public class PointOfInterestEdit extends JComponent {
|
public class PointOfInterestEdit extends JComponent {
|
||||||
|
|
||||||
@@ -18,16 +24,29 @@ public class PointOfInterestEdit extends JComponent {
|
|||||||
JSpinner radiusFactor= new JSpinner(new SpinnerNumberModel(0.0f, 0.0f, 2.0f, 0.1f));
|
JSpinner radiusFactor= new JSpinner(new SpinnerNumberModel(0.0f, 0.0f, 2.0f, 0.1f));
|
||||||
SwingAtlasPreview preview=new SwingAtlasPreview(256,2000);
|
SwingAtlasPreview preview=new SwingAtlasPreview(256,2000);
|
||||||
|
|
||||||
|
JTextField manualEntry = new JTextField(20);
|
||||||
|
DefaultListModel<String> existingModel = new DefaultListModel<>();
|
||||||
|
DefaultListModel<String> POIModel = new DefaultListModel<>();
|
||||||
|
JList<String> existingTags;
|
||||||
|
JList<String> POITags;
|
||||||
|
|
||||||
private boolean updating=false;
|
private boolean updating=false;
|
||||||
|
|
||||||
public PointOfInterestEdit()
|
public PointOfInterestEdit()
|
||||||
{
|
{
|
||||||
|
JTabbedPane tabs = new JTabbedPane();
|
||||||
|
add(tabs, BorderLayout.CENTER);
|
||||||
|
|
||||||
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
|
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
|
||||||
FormPanel parameters=new FormPanel();
|
FormPanel parameters=new FormPanel();
|
||||||
|
//parameters.setLayout(new BoxLayout(parameters, BoxLayout.Y_AXIS));
|
||||||
parameters.setBorder(BorderFactory.createTitledBorder("Parameter"));
|
parameters.setBorder(BorderFactory.createTitledBorder("Parameter"));
|
||||||
|
|
||||||
|
JPanel tags = new JPanel();
|
||||||
|
|
||||||
|
tabs.addTab("Basic Info", parameters);
|
||||||
|
tabs.addTab("Quest Tags", tags);
|
||||||
|
|
||||||
parameters.add("Name:",name);
|
parameters.add("Name:",name);
|
||||||
parameters.add("Type:",type);
|
parameters.add("Type:",type);
|
||||||
parameters.add("Count:",count);
|
parameters.add("Count:",count);
|
||||||
@@ -37,15 +56,137 @@ public class PointOfInterestEdit extends JComponent {
|
|||||||
parameters.add("Radius factor:",radiusFactor);
|
parameters.add("Radius factor:",radiusFactor);
|
||||||
parameters.add(preview);
|
parameters.add(preview);
|
||||||
|
|
||||||
add(parameters);
|
name.getDocument().addDocumentListener(new DocumentChangeListener(PointOfInterestEdit.this::updateItem));
|
||||||
|
type.getDocument().addDocumentListener(new DocumentChangeListener(PointOfInterestEdit.this::updateItem));
|
||||||
name.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
|
|
||||||
type.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
|
|
||||||
count.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
|
count.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
|
||||||
spriteAtlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
|
spriteAtlas.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(PointOfInterestEdit.this::updateItem));
|
||||||
sprite.getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
|
sprite.getDocument().addDocumentListener(new DocumentChangeListener(PointOfInterestEdit.this::updateItem));
|
||||||
map.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(() -> PointOfInterestEdit.this.updateItem()));
|
map.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(PointOfInterestEdit.this::updateItem));
|
||||||
radiusFactor.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
|
radiusFactor.addChangeListener(e -> PointOfInterestEdit.this.updateItem());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
existingTags = new JList<>();
|
||||||
|
|
||||||
|
|
||||||
|
existingTags.getInputMap(JList.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
|
||||||
|
KeyStroke.getKeyStroke("ENTER"), "addSelected");
|
||||||
|
existingTags.getActionMap().put("addSelected", new AbstractAction() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
int index = existingTags.getSelectedIndex();
|
||||||
|
|
||||||
|
String selectedItem = existingTags.getSelectedValue();
|
||||||
|
|
||||||
|
if (selectedItem != null) {
|
||||||
|
POIModel.addElement(selectedItem);
|
||||||
|
existingTags.grabFocus();
|
||||||
|
existingTags.setSelectedIndex(index<existingModel.size()?index:index-1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
existingModel = QuestController.getInstance().getPOITags(true);
|
||||||
|
existingTags.setModel(existingModel);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
POITags = new JList<>();
|
||||||
|
POIModel = new DefaultListModel<>();
|
||||||
|
POITags.setModel(POIModel);
|
||||||
|
|
||||||
|
POITags.getModel().addListDataListener(new ListDataListener() {
|
||||||
|
@Override
|
||||||
|
public void intervalAdded(ListDataEvent e) {
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void intervalRemoved(ListDataEvent e) {
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contentsChanged(ListDataEvent e) {
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JButton select = new JButton("Select");
|
||||||
|
select.addActionListener(q -> addSelected());
|
||||||
|
JButton add = new JButton("Manual Add");
|
||||||
|
add.addActionListener(q -> manualAdd(POIModel));
|
||||||
|
JButton remove = new JButton("Remove Item");
|
||||||
|
remove.addActionListener(q -> removeSelected());
|
||||||
|
|
||||||
|
tags.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
JPanel left = new JPanel();
|
||||||
|
left.setLayout(new BorderLayout());
|
||||||
|
left.add(new JLabel("Tags already in use"), BorderLayout.NORTH);
|
||||||
|
JScrollPane listScroller = new JScrollPane(existingTags);
|
||||||
|
listScroller.setMinimumSize(new Dimension(400, 800));
|
||||||
|
left.add(listScroller, BorderLayout.CENTER);
|
||||||
|
tags.add(left, BorderLayout.WEST);
|
||||||
|
|
||||||
|
FormPanel tagEdit = new FormPanel();
|
||||||
|
tagEdit.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
FormPanel mappedTags = new FormPanel();
|
||||||
|
mappedTags.setLayout(new BorderLayout());
|
||||||
|
mappedTags.add(new JLabel("Tags Mapped to this object"), BorderLayout.NORTH);
|
||||||
|
JScrollPane listScroller2 = new JScrollPane(POITags);
|
||||||
|
listScroller2.setMinimumSize(new Dimension(400, 800));
|
||||||
|
mappedTags.add(listScroller2, BorderLayout.CENTER);
|
||||||
|
tagEdit.add(mappedTags,BorderLayout.EAST);
|
||||||
|
|
||||||
|
JPanel controlPanel = new JPanel();
|
||||||
|
|
||||||
|
controlPanel.add(select);
|
||||||
|
controlPanel.add(add);
|
||||||
|
controlPanel.add(manualEntry);
|
||||||
|
|
||||||
|
manualEntry.getInputMap(JList.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
|
||||||
|
KeyStroke.getKeyStroke("ENTER"), "addTyped");
|
||||||
|
manualEntry.getActionMap().put("addTyped", new AbstractAction() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
|
||||||
|
if (!manualEntry.getText().trim().isEmpty()) {
|
||||||
|
manualAdd(POIModel);
|
||||||
|
manualEntry.grabFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
controlPanel.add(remove);
|
||||||
|
tagEdit.add(controlPanel, BorderLayout.CENTER);
|
||||||
|
tags.add(tagEdit,BorderLayout.CENTER);
|
||||||
|
|
||||||
|
JTextArea right1 = new JTextArea("This is really just to pad some space\n" +
|
||||||
|
"but also to explain the use of tags.\n" +
|
||||||
|
"Rather than adding 100's of object names\n" +
|
||||||
|
"to every quest definition, instead we will\n"+
|
||||||
|
"categorize enemies and points of interest with\n"+
|
||||||
|
"tags and reference those categories in quests");
|
||||||
|
right1.setEnabled(false);
|
||||||
|
tags.add(right1, BorderLayout.EAST);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +195,20 @@ public class PointOfInterestEdit extends JComponent {
|
|||||||
return;
|
return;
|
||||||
currentData.name=name.getText();
|
currentData.name=name.getText();
|
||||||
currentData.type= type.getText();
|
currentData.type= type.getText();
|
||||||
currentData.count= ((Integer) count.getValue()).intValue();
|
currentData.count= (Integer) count.getValue();
|
||||||
currentData.spriteAtlas=spriteAtlas.getEdit().getText();
|
currentData.spriteAtlas=spriteAtlas.getEdit().getText();
|
||||||
currentData.sprite=sprite.getText();
|
currentData.sprite=sprite.getText();
|
||||||
currentData.map=map.getEdit().getText();
|
currentData.map=map.getEdit().getText();
|
||||||
currentData.radiusFactor=((Float) radiusFactor.getValue()).floatValue();
|
currentData.radiusFactor= (Float) radiusFactor.getValue();
|
||||||
|
|
||||||
|
ArrayList<String> tags = new ArrayList<>();
|
||||||
|
for (Enumeration<String> e = POIModel.elements(); e.hasMoreElements();){
|
||||||
|
tags.add(e.nextElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentData.questTags = tags.toArray(currentData.questTags);
|
||||||
|
QuestController.getInstance().refresh();
|
||||||
|
filterExisting(POIModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrent(PointOfInterestData data)
|
public void setCurrent(PointOfInterestData data)
|
||||||
@@ -67,6 +217,36 @@ public class PointOfInterestEdit extends JComponent {
|
|||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addSelected(){
|
||||||
|
if (existingTags.getSelectedIndex()>-1)
|
||||||
|
POIModel.addElement(existingTags.getModel().getElementAt(existingTags.getSelectedIndex()));
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeSelected(){
|
||||||
|
if (POITags.getSelectedIndex()>-1)
|
||||||
|
POIModel.remove(POITags.getSelectedIndex());
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterExisting(DefaultListModel<String> filter){
|
||||||
|
DefaultListModel<String> toReturn = new DefaultListModel<>();
|
||||||
|
for (Enumeration<String> e = QuestController.getInstance().getPOITags(true).elements(); e.hasMoreElements();){
|
||||||
|
String toTest = e.nextElement();
|
||||||
|
if (toTest != null & !filter.contains(toTest)){
|
||||||
|
toReturn.addElement(toTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
existingTags.setModel(toReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void manualAdd(DefaultListModel<String> model){
|
||||||
|
if (!manualEntry.getText().trim().isEmpty())
|
||||||
|
model.addElement(manualEntry.getText().trim());
|
||||||
|
manualEntry.setText("");
|
||||||
|
updateItem();
|
||||||
|
}
|
||||||
|
|
||||||
private void refresh() {
|
private void refresh() {
|
||||||
setEnabled(currentData!=null);
|
setEnabled(currentData!=null);
|
||||||
if(currentData==null)
|
if(currentData==null)
|
||||||
@@ -83,6 +263,12 @@ public class PointOfInterestEdit extends JComponent {
|
|||||||
radiusFactor.setValue(currentData.radiusFactor);
|
radiusFactor.setValue(currentData.radiusFactor);
|
||||||
|
|
||||||
preview.setSpritePath(currentData.spriteAtlas,currentData.sprite);
|
preview.setSpritePath(currentData.spriteAtlas,currentData.sprite);
|
||||||
|
POIModel.clear();
|
||||||
|
for(String val : currentData.questTags) {
|
||||||
|
if (val != null)
|
||||||
|
POIModel.addElement(val);
|
||||||
|
}
|
||||||
|
filterExisting(POIModel);
|
||||||
updating=false;
|
updating=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class PointOfInterestEditor extends JComponent {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class PointOfInterestRenderer extends DefaultListCellRenderer {
|
public static class PointOfInterestRenderer extends DefaultListCellRenderer {
|
||||||
@Override
|
@Override
|
||||||
public Component getListCellRendererComponent(
|
public Component getListCellRendererComponent(
|
||||||
JList list, Object value, int index,
|
JList list, Object value, int index,
|
||||||
@@ -71,6 +71,7 @@ public class PointOfInterestEditor extends JComponent {
|
|||||||
BorderLayout layout=new BorderLayout();
|
BorderLayout layout=new BorderLayout();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
add(new JScrollPane(list), BorderLayout.LINE_START);
|
add(new JScrollPane(list), BorderLayout.LINE_START);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
add(toolBar, BorderLayout.PAGE_START);
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
add(edit,BorderLayout.CENTER);
|
add(edit,BorderLayout.CENTER);
|
||||||
load();
|
load();
|
||||||
@@ -109,12 +110,13 @@ public class PointOfInterestEditor extends JComponent {
|
|||||||
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
|
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
|
||||||
if (handle.exists())
|
if (handle.exists())
|
||||||
{
|
{
|
||||||
Array readEnemies=json.fromJson(Array.class, PointOfInterestData.class, handle);
|
allEnemies =json.fromJson(Array.class, PointOfInterestData.class, handle);
|
||||||
allEnemies = readEnemies;
|
|
||||||
}
|
}
|
||||||
for (int i=0;i<allEnemies.size;i++) {
|
for (int i=0;i<allEnemies.size;i++) {
|
||||||
model.add(i,allEnemies.get(i));
|
model.add(i,allEnemies.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QuestController.getInstance().load();
|
||||||
}
|
}
|
||||||
void addItem()
|
void addItem()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,228 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Json;
|
||||||
|
import com.badlogic.gdx.utils.JsonWriter;
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
|
import forge.adventure.data.EnemyData;
|
||||||
|
import forge.adventure.data.PointOfInterestData;
|
||||||
|
import forge.adventure.util.Config;
|
||||||
|
import forge.adventure.util.Paths;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class QuestController {
|
||||||
|
|
||||||
|
public final DefaultListModel<String> POITags = new DefaultListModel<>();
|
||||||
|
public final DefaultListModel<String> enemyTags = new DefaultListModel<>();
|
||||||
|
public final DefaultListModel<String> questEnemyTags = new DefaultListModel<>();
|
||||||
|
public final DefaultListModel<String> questTags = new DefaultListModel<>();
|
||||||
|
public final DefaultListModel<String> questPOITags = new DefaultListModel<>();
|
||||||
|
private final DefaultListModel<PointOfInterestData> allPOI = new DefaultListModel<>();
|
||||||
|
private final DefaultListModel<EnemyData> allEnemies = new DefaultListModel<>();
|
||||||
|
|
||||||
|
private final DefaultListModel<AdventureQuestData> allQuests = new DefaultListModel<>();
|
||||||
|
|
||||||
|
private static QuestController instance;
|
||||||
|
|
||||||
|
public static QuestController getInstance() {
|
||||||
|
if (instance == null)
|
||||||
|
instance = new QuestController();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultListModel<AdventureQuestData> getAllQuests() {
|
||||||
|
return allQuests;
|
||||||
|
}
|
||||||
|
|
||||||
|
private QuestController(){
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultListModel<String> getEnemyTags(boolean includeQuest){
|
||||||
|
DefaultListModel<String> toReturn = new DefaultListModel<>();
|
||||||
|
for (int i = 0; i < enemyTags.size(); i++){
|
||||||
|
toReturn.removeElement(enemyTags.get(i));
|
||||||
|
toReturn.addElement(enemyTags.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeQuest){
|
||||||
|
for (int i = 0; i < questEnemyTags.size(); i++)
|
||||||
|
{
|
||||||
|
toReturn.removeElement(questEnemyTags.get(i));
|
||||||
|
toReturn.addElement(questEnemyTags.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> sortedObjects = Arrays.stream(toReturn.toArray()).sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
|
toReturn.clear();
|
||||||
|
|
||||||
|
for (Object sortedObject : sortedObjects) {
|
||||||
|
toReturn.addElement((String) sortedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultListModel<String> getPOITags(boolean includeQuest){
|
||||||
|
DefaultListModel<String> toReturn = new DefaultListModel<>();
|
||||||
|
for (int i = 0; i < POITags.size(); i++){
|
||||||
|
toReturn.removeElement(POITags.get(i));
|
||||||
|
toReturn.addElement(POITags.get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeQuest){
|
||||||
|
for (int i = 0; i < questEnemyTags.size(); i++)
|
||||||
|
{
|
||||||
|
toReturn.removeElement(questEnemyTags.get(i));
|
||||||
|
toReturn.addElement(questEnemyTags.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> sortedObjects = Arrays.stream(toReturn.toArray()).sorted().collect(Collectors.toList());
|
||||||
|
|
||||||
|
toReturn.clear();
|
||||||
|
|
||||||
|
for (Object sortedObject : sortedObjects) {
|
||||||
|
toReturn.addElement((String) sortedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh(){
|
||||||
|
enemyTags.clear();
|
||||||
|
POITags.clear();
|
||||||
|
questPOITags.clear();
|
||||||
|
questEnemyTags.clear();
|
||||||
|
questTags.clear();
|
||||||
|
|
||||||
|
for (int i=0;i<allEnemies.size();i++) {
|
||||||
|
for (String tag : allEnemies.get(i).questTags)
|
||||||
|
{
|
||||||
|
enemyTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
enemyTags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<allPOI.size();i++) {
|
||||||
|
for (String tag : allPOI.get(i).questTags)
|
||||||
|
{
|
||||||
|
POITags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
POITags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0;i<allQuests.size();i++) {
|
||||||
|
|
||||||
|
for (String tag : allQuests.get(i).questTags)
|
||||||
|
{
|
||||||
|
questTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questTags.addElement(tag);
|
||||||
|
}
|
||||||
|
for (String tag : allQuests.get(i).questEnemyTags)
|
||||||
|
{
|
||||||
|
questEnemyTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questEnemyTags.addElement(tag);
|
||||||
|
}
|
||||||
|
for (String tag : allQuests.get(i).questPOITags)
|
||||||
|
{
|
||||||
|
questPOITags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questPOITags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load()
|
||||||
|
{
|
||||||
|
allEnemies.clear();
|
||||||
|
Array<EnemyData> enemyJSON=new Array<>();
|
||||||
|
Json json = new Json();
|
||||||
|
FileHandle handle = Config.instance().getFile(Paths.ENEMIES);
|
||||||
|
if (handle.exists())
|
||||||
|
{
|
||||||
|
enemyJSON = json.fromJson(Array.class, EnemyData.class, handle);
|
||||||
|
}
|
||||||
|
for (int i=0;i<enemyJSON.size;i++) {
|
||||||
|
allEnemies.add(i,enemyJSON.get(i));
|
||||||
|
for (String tag : enemyJSON.get(i).questTags)
|
||||||
|
{
|
||||||
|
enemyTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
enemyTags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allPOI.clear();
|
||||||
|
Array<PointOfInterestData> POIJSON=new Array<>();
|
||||||
|
json = new Json();
|
||||||
|
handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
|
||||||
|
if (handle.exists())
|
||||||
|
{
|
||||||
|
POIJSON = json.fromJson(Array.class, PointOfInterestData.class, handle);
|
||||||
|
}
|
||||||
|
for (int i=0;i<POIJSON.size;i++) {
|
||||||
|
allPOI.add(i,POIJSON.get(i));
|
||||||
|
for (String tag : POIJSON.get(i).questTags)
|
||||||
|
{
|
||||||
|
POITags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
POITags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allQuests.clear();
|
||||||
|
Array<AdventureQuestData> questJSON=new Array<>();
|
||||||
|
json = new Json();
|
||||||
|
handle = Config.instance().getFile(Paths.QUESTS);
|
||||||
|
if (handle.exists())
|
||||||
|
{
|
||||||
|
questJSON = json.fromJson(Array.class, AdventureQuestData.class, handle);
|
||||||
|
}
|
||||||
|
for (int i=0;i<questJSON.size;i++) {
|
||||||
|
AdventureQuestData template = questJSON.get(i);
|
||||||
|
template.isTemplate = true;
|
||||||
|
|
||||||
|
allQuests.add(i,template);
|
||||||
|
|
||||||
|
for (String tag : template.questTags)
|
||||||
|
{
|
||||||
|
questTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questTags.addElement(tag);
|
||||||
|
}
|
||||||
|
for (String tag : template.questEnemyTags)
|
||||||
|
{
|
||||||
|
questEnemyTags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questEnemyTags.addElement(tag);
|
||||||
|
}
|
||||||
|
for (String tag : template.questPOITags)
|
||||||
|
{
|
||||||
|
questPOITags.removeElement(tag); //Ensure uniqueness
|
||||||
|
if (tag!= null)
|
||||||
|
questPOITags.addElement(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void save()
|
||||||
|
{
|
||||||
|
Json json = new Json(JsonWriter.OutputType.json);
|
||||||
|
FileHandle handle = Config.instance().getFile(Paths.QUESTS);
|
||||||
|
AdventureQuestData[] saveData = Arrays.stream(allQuests.toArray()).map(AdventureQuestData.class::cast).toArray(AdventureQuestData[]::new);
|
||||||
|
|
||||||
|
handle.writeString(json.prettyPrint(json.toJson(saveData,Array.class, AdventureQuestData.class)),false);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
public class QuestEdit extends FormPanel {
|
||||||
|
AdventureQuestData currentData;
|
||||||
|
//public JSpinner spawnWeight= new JSpinner(new SpinnerNumberModel(0.0f, 0.f, 1f, 0.1f));
|
||||||
|
public JLabel id = new JLabel();
|
||||||
|
public JTextField name=new JTextField();
|
||||||
|
public JTextField description=new JTextField();
|
||||||
|
public JTextField synopsis=new JTextField();
|
||||||
|
public JCheckBox storyQuest = new JCheckBox();
|
||||||
|
public JTextField rewardDescription=new JTextField();
|
||||||
|
public QuestStageEditor stages =new QuestStageEditor();
|
||||||
|
|
||||||
|
|
||||||
|
JTabbedPane tabs =new JTabbedPane();
|
||||||
|
public DialogEditor prologueEditor =new DialogEditor();
|
||||||
|
public DialogEditor epilogueEditor =new DialogEditor();
|
||||||
|
public DialogEditor offerEditor = new DialogEditor();
|
||||||
|
public DialogEditor failureEditor = new DialogEditor();
|
||||||
|
public DialogEditor declineEditor = new DialogEditor();
|
||||||
|
private boolean updating=false;
|
||||||
|
|
||||||
|
public QuestEdit()
|
||||||
|
{
|
||||||
|
|
||||||
|
FormPanel center=new FormPanel() { };
|
||||||
|
|
||||||
|
center.add("Quest ID:", id);
|
||||||
|
center.add("Name:",name);
|
||||||
|
//center.add("Synopsis (dev mode):",synopsis);
|
||||||
|
center.add("Description:",description);
|
||||||
|
center.add("Reward Description:",rewardDescription);
|
||||||
|
center.add("Storyline Quest", storyQuest);
|
||||||
|
|
||||||
|
add(center);
|
||||||
|
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
add(tabs);
|
||||||
|
tabs.add("Quest Stages", getStagesTab());
|
||||||
|
tabs.add("Offer Dialog",getOfferTab());
|
||||||
|
tabs.add("Prologue",getPrologueTab());
|
||||||
|
tabs.add("Epilogue",getEpilogueTab());
|
||||||
|
tabs.add("Failure Dialog", getFailureTab());
|
||||||
|
tabs.add("Decline Dialog",getDeclineTab());
|
||||||
|
|
||||||
|
name.getDocument().addDocumentListener(new DocumentChangeListener(QuestEdit.this::updateQuest));
|
||||||
|
description.getDocument().addDocumentListener(new DocumentChangeListener(QuestEdit.this::updateQuest));
|
||||||
|
synopsis.getDocument().addDocumentListener(new DocumentChangeListener(QuestEdit.this::updateQuest));
|
||||||
|
storyQuest.getModel().addChangeListener(q -> QuestEdit.this.updateQuest());
|
||||||
|
rewardDescription.getDocument().addDocumentListener(new DocumentChangeListener(QuestEdit.this::updateQuest));
|
||||||
|
stages.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
offerEditor.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
prologueEditor.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
epilogueEditor.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
failureEditor.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
declineEditor.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
stages.addChangeListener(e -> QuestEdit.this.updateQuest());
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateQuest() {
|
||||||
|
if(currentData==null||updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentData.name = name.getText();
|
||||||
|
currentData.storyQuest = storyQuest.isSelected();
|
||||||
|
currentData.synopsis = synopsis.getText();
|
||||||
|
currentData.description = description.getText();
|
||||||
|
currentData.rewardDescription = rewardDescription.getText();
|
||||||
|
currentData.stages = stages.getStages();
|
||||||
|
currentData.offerDialog = offerEditor.getDialogData();
|
||||||
|
currentData.prologue = prologueEditor.getDialogData();
|
||||||
|
currentData.epilogue = epilogueEditor.getDialogData();
|
||||||
|
currentData.failureDialog = failureEditor.getDialogData();
|
||||||
|
currentData.declinedDialog = declineEditor.getDialogData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentQuest(AdventureQuestData data)
|
||||||
|
{
|
||||||
|
currentData=data;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
setEnabled(currentData!=null);
|
||||||
|
if(currentData==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setVisible(true);
|
||||||
|
updating=true;
|
||||||
|
id.setText(currentData.getID() + "");
|
||||||
|
name.setText(currentData.name);
|
||||||
|
description.setText(currentData.description);
|
||||||
|
synopsis.setText(currentData.synopsis);
|
||||||
|
storyQuest.getModel().setSelected(currentData.storyQuest);
|
||||||
|
rewardDescription.setText(currentData.rewardDescription);
|
||||||
|
stages.setStages(currentData);
|
||||||
|
|
||||||
|
offerEditor.loadData(currentData.offerDialog);
|
||||||
|
prologueEditor.loadData(currentData.prologue);
|
||||||
|
epilogueEditor.loadData(currentData.epilogue);
|
||||||
|
failureEditor.loadData(currentData.failureDialog);
|
||||||
|
declineEditor.loadData(currentData.declinedDialog);
|
||||||
|
|
||||||
|
updating=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getOfferTab(){
|
||||||
|
JPanel offerTab = new JPanel();
|
||||||
|
offerTab.setLayout(new BoxLayout(offerTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(offerEditor);
|
||||||
|
offerTab.add(center);
|
||||||
|
return offerTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getPrologueTab(){
|
||||||
|
JPanel prologueTab = new JPanel();
|
||||||
|
prologueTab.setLayout(new BoxLayout(prologueTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(prologueEditor);
|
||||||
|
prologueTab.add(center);
|
||||||
|
return prologueTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getEpilogueTab(){
|
||||||
|
JPanel epilogueTab = new JPanel();
|
||||||
|
epilogueTab.setLayout(new BoxLayout(epilogueTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(epilogueEditor);
|
||||||
|
epilogueTab.add(center);
|
||||||
|
return epilogueTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getFailureTab(){
|
||||||
|
JPanel failureTab = new JPanel();
|
||||||
|
failureTab.setLayout(new BoxLayout(failureTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(failureEditor);
|
||||||
|
failureTab.add(center);
|
||||||
|
return failureTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getDeclineTab(){
|
||||||
|
JPanel declineTab = new JPanel();
|
||||||
|
declineTab.setLayout(new BoxLayout(declineTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(declineEditor);
|
||||||
|
declineTab.add(center);
|
||||||
|
return declineTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getStagesTab(){
|
||||||
|
JPanel stagesTab = new JPanel();
|
||||||
|
stagesTab.setLayout(new BoxLayout(stagesTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(stages);
|
||||||
|
stagesTab.add(center);
|
||||||
|
return stagesTab;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Json;
|
||||||
|
import com.badlogic.gdx.utils.JsonWriter;
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
|
import forge.adventure.util.Config;
|
||||||
|
import forge.adventure.util.Paths;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class QuestEditor extends JComponent {
|
||||||
|
JList<AdventureQuestData> list = new JList<>(QuestController.getInstance().getAllQuests());
|
||||||
|
JToolBar toolBar = new JToolBar("toolbar");
|
||||||
|
QuestEdit edit=new QuestEdit();
|
||||||
|
|
||||||
|
public class QuestDataRenderer extends DefaultListCellRenderer {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean cellHasFocus) {
|
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
if(!(value instanceof AdventureQuestData))
|
||||||
|
return label;
|
||||||
|
AdventureQuestData quest=(AdventureQuestData) value;
|
||||||
|
// Get the renderer component from parent class
|
||||||
|
|
||||||
|
label.setText(quest.name);
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void addButton(String name,ActionListener action)
|
||||||
|
{
|
||||||
|
JButton newButton=new JButton(name);
|
||||||
|
newButton.addActionListener(action);
|
||||||
|
toolBar.add(newButton);
|
||||||
|
|
||||||
|
}
|
||||||
|
public QuestEditor()
|
||||||
|
{
|
||||||
|
|
||||||
|
list.setCellRenderer(new QuestDataRenderer());
|
||||||
|
list.addListSelectionListener(e -> QuestEditor.this.updateEdit());
|
||||||
|
addButton("Add Quest", e -> QuestEditor.this.addStage());
|
||||||
|
addButton("Remove", e -> QuestEditor.this.remove());
|
||||||
|
addButton("Copy", e -> QuestEditor.this.copy());
|
||||||
|
addButton("Load", e -> QuestController.getInstance().load());
|
||||||
|
addButton("Save", e -> QuestEditor.this.save());
|
||||||
|
BorderLayout layout=new BorderLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
add(new JScrollPane(list), BorderLayout.LINE_START);
|
||||||
|
toolBar.setFloatable(false);
|
||||||
|
add(toolBar, BorderLayout.PAGE_START);
|
||||||
|
add(edit,BorderLayout.CENTER);
|
||||||
|
edit.setVisible(false);
|
||||||
|
}
|
||||||
|
private void copy() {
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
AdventureQuestData data=new AdventureQuestData(QuestController.getInstance().getAllQuests().get(selected));
|
||||||
|
data.isTemplate = true;
|
||||||
|
QuestController.getInstance().getAllQuests().add(QuestController.getInstance().getAllQuests().size(),data);
|
||||||
|
}
|
||||||
|
private void updateEdit() {
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
edit.setCurrentQuest(QuestController.getInstance().getAllQuests().get(selected));
|
||||||
|
}
|
||||||
|
|
||||||
|
void save()
|
||||||
|
{
|
||||||
|
Array<AdventureQuestData> allQuests=new Array<>();
|
||||||
|
for(int i=0;i<QuestController.getInstance().getAllQuests().getSize();i++) {
|
||||||
|
allQuests.add(QuestController.getInstance().getAllQuests().get(i));
|
||||||
|
}
|
||||||
|
Json json = new Json(JsonWriter.OutputType.json);
|
||||||
|
FileHandle handle = Config.instance().getFile(Paths.QUESTS);
|
||||||
|
handle.writeString(json.prettyPrint(json.toJson(allQuests,Array.class, AdventureQuestData.class)),false);
|
||||||
|
QuestController.getInstance().save();
|
||||||
|
}
|
||||||
|
void addStage()
|
||||||
|
{
|
||||||
|
AdventureQuestData data=new AdventureQuestData();
|
||||||
|
data.name="New Quest "+QuestController.getInstance().getAllQuests().getSize();
|
||||||
|
data.isTemplate = true;
|
||||||
|
QuestController.getInstance().getAllQuests().add(QuestController.getInstance().getAllQuests().size(),data);
|
||||||
|
}
|
||||||
|
void remove()
|
||||||
|
{
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
QuestController.getInstance().getAllQuests().remove(selected);
|
||||||
|
edit.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,607 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.*;
|
||||||
|
import forge.adventure.util.AdventureQuestController;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class QuestStageEdit extends FormPanel {
|
||||||
|
private boolean updating=false;
|
||||||
|
AdventureQuestStage currentData;
|
||||||
|
AdventureQuestData currentQuestData;
|
||||||
|
public JTextField name=new JTextField("", 25);
|
||||||
|
public JTextField description=new JTextField("", 25);
|
||||||
|
public TextListEdit itemNames =new TextListEdit();
|
||||||
|
public TextListEdit spriteNames =new TextListEdit();
|
||||||
|
public TextListEdit equipNames =new TextListEdit();
|
||||||
|
public TextListEdit prerequisites =new TextListEdit(currentQuestData!=null?(String[])Arrays.stream(currentQuestData.stages).filter(q -> !q.equals(currentData)).toArray():new String[]{}); //May not be the right way to do this, will come back to it.
|
||||||
|
|
||||||
|
JTabbedPane tabs =new JTabbedPane();
|
||||||
|
DialogEditor prologueEditor = new DialogEditor();
|
||||||
|
DialogEditor epilogueEditor = new DialogEditor();
|
||||||
|
|
||||||
|
public QuestStageEdit()
|
||||||
|
{
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
add(getInfoTab());
|
||||||
|
add(tabs);
|
||||||
|
tabs.add("Objective", getObjectiveTab());
|
||||||
|
tabs.add("Prologue",getPrologueTab());
|
||||||
|
tabs.add("Epilogue",getEpilogueTab());
|
||||||
|
tabs.add("Prerequisites",getPrereqTab());
|
||||||
|
|
||||||
|
//temp
|
||||||
|
nyi.setForeground(Color.red);
|
||||||
|
//
|
||||||
|
|
||||||
|
addListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getInfoTab(){
|
||||||
|
JPanel infoTab = new JPanel();
|
||||||
|
FormPanel center=new FormPanel();
|
||||||
|
center.add("name:",name);
|
||||||
|
center.add("description:",description);
|
||||||
|
name.setSize(400, name.getHeight());
|
||||||
|
description.setSize(400, description.getHeight());
|
||||||
|
infoTab.add(center);
|
||||||
|
name.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
description.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
prerequisites.getEdit().getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
return infoTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getPrologueTab(){
|
||||||
|
JPanel prologueTab = new JPanel();
|
||||||
|
prologueTab.setLayout(new BoxLayout(prologueTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(prologueEditor);
|
||||||
|
prologueTab.add(center);
|
||||||
|
return prologueTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getEpilogueTab(){
|
||||||
|
JPanel epilogueTab = new JPanel();
|
||||||
|
epilogueTab.setLayout(new BoxLayout(epilogueTab, BoxLayout.Y_AXIS));
|
||||||
|
FormPanel center = new FormPanel();
|
||||||
|
center.add(epilogueEditor);
|
||||||
|
epilogueTab.add(center);
|
||||||
|
return epilogueTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JComboBox<AdventureQuestController.ObjectiveTypes> objectiveType;
|
||||||
|
|
||||||
|
private final JLabel nyi = new JLabel("Not yet implemented");
|
||||||
|
private final JTextField deliveryItem=new JTextField(25);
|
||||||
|
private final JTextField mapFlag = new JTextField(25);
|
||||||
|
|
||||||
|
private Box mapFlagGroup;
|
||||||
|
private final JSpinner flagSpinner = new JSpinner(new SpinnerNumberModel(1, 1, 1000, 1));
|
||||||
|
private Box flagValueGroup;
|
||||||
|
private final JCheckBox anyPOI = new JCheckBox("Any Point of Interest matching");
|
||||||
|
private final JCheckBox here = new JCheckBox("Use current map instead of selecting tags");
|
||||||
|
private final JCheckBox mixedEnemies = new JCheckBox("Mixture of enemy types matching");
|
||||||
|
private final JLabel count1Description = new JLabel("(Count 1 description)");
|
||||||
|
private final JLabel count2Description = new JLabel("(Count 2 description)");
|
||||||
|
private final JLabel count3Description = new JLabel("(Count 3 description)");
|
||||||
|
private final JSpinner count1Spinner = new JSpinner(new SpinnerNumberModel(1, 0, 100, 1));
|
||||||
|
private final JSpinner count2Spinner = new JSpinner(new SpinnerNumberModel(1, 0, 100, 1));
|
||||||
|
private final JSpinner count3Spinner = new JSpinner(new SpinnerNumberModel(1, 0, 100, 1));
|
||||||
|
|
||||||
|
private final JLabel arenaLabel = new JLabel("Enter the arena and prove your worth. (Note: Please be sure the PoIs selected have an arena)");
|
||||||
|
private final JLabel clearLabel = new JLabel("Clear all enemies from the target area.");
|
||||||
|
private final JLabel defeatLabel = new JLabel("Defeat a number of enemies of the indicated type.");
|
||||||
|
private final JLabel deliveryLabel = new JLabel("Travel to the given destination to deliver an item (not tracked in inventory).");
|
||||||
|
private final JLabel escortLabel = new JLabel("Protect your target as they travel to their destination.");
|
||||||
|
private final JLabel fetchLabel = new JLabel("Obtain the requested items (not tracked in inventory).");
|
||||||
|
private final JLabel findLabel = new JLabel("Locate the and enter a PoI.");
|
||||||
|
private final JLabel gatherLabel = new JLabel("Have the requested item in your inventory (tracked in inventory)");
|
||||||
|
private final JLabel giveLabel = new JLabel("Have the requested items removed from your inventory.");
|
||||||
|
private final JLabel huntLabel = new JLabel("Track down and defeat your target (on the overworld map).");
|
||||||
|
private final JLabel leaveLabel = new JLabel("Exit the current PoI and return to the overworld map.");
|
||||||
|
private final JLabel noneLabel = new JLabel("No visible objective. Use in coordination with hidden parallel objectives to track when to progress");
|
||||||
|
private final JLabel patrolLabel = new JLabel("Get close to generated coordinates before starting your next objective");
|
||||||
|
private final JLabel rescueLabel = new JLabel("Reach and rescue the target");
|
||||||
|
private final JLabel siegeLabel = new JLabel("Travel to the target location and defeat enemies attacking it");
|
||||||
|
private final JLabel mapFlagLabel = new JLabel("Have a map flag set to a minimum value");
|
||||||
|
private final JLabel questFlagLabel = new JLabel("Have a global quest flag set to a minimum value");
|
||||||
|
private final JLabel travelLabel = new JLabel("Travel to the given destination.");
|
||||||
|
private final JLabel useLabel = new JLabel("Use the indicated item from your inventory.");
|
||||||
|
private JTabbedPane poiPane = new JTabbedPane();
|
||||||
|
private final QuestTagSelector poiSelector = new QuestTagSelector("Destination Tags", false,true);
|
||||||
|
private final QuestTagSelector enemySelector = new QuestTagSelector("Enemy Tags", true,false);
|
||||||
|
private final JTextField poiTokenInput = new JTextField(25);
|
||||||
|
|
||||||
|
private final JLabel poiTokenLabel = new JLabel();
|
||||||
|
private final JLabel poiTokenDescription = new JLabel(
|
||||||
|
"At the bottom of many objectives involving a PoI, you will see a text field in the format of '$poi_#'." +
|
||||||
|
"Enter that tag here to ignore the PoI tag selector of this stage and instead use the same PoI that was selected " +
|
||||||
|
"for that stage as the target PoI for this one as well.");
|
||||||
|
|
||||||
|
private void hideAllControls(){
|
||||||
|
arenaLabel.setVisible(false);
|
||||||
|
clearLabel.setVisible(false);
|
||||||
|
deliveryLabel.setVisible(false);
|
||||||
|
defeatLabel.setVisible(false);
|
||||||
|
escortLabel.setVisible(false);
|
||||||
|
fetchLabel.setVisible(false);
|
||||||
|
findLabel.setVisible(false);
|
||||||
|
gatherLabel.setVisible(false);
|
||||||
|
giveLabel.setVisible(false);
|
||||||
|
huntLabel.setVisible(false);
|
||||||
|
leaveLabel.setVisible(false);
|
||||||
|
noneLabel.setVisible(false);
|
||||||
|
patrolLabel.setVisible(false);
|
||||||
|
rescueLabel.setVisible(false);
|
||||||
|
siegeLabel.setVisible(false);
|
||||||
|
mapFlagLabel.setVisible(false);
|
||||||
|
questFlagLabel.setVisible(false);
|
||||||
|
travelLabel.setVisible(false);
|
||||||
|
useLabel.setVisible(false);
|
||||||
|
deliveryItem.setVisible(false);
|
||||||
|
mapFlagGroup.setVisible(false);
|
||||||
|
flagValueGroup.setVisible(false);
|
||||||
|
anyPOI.setVisible(false);
|
||||||
|
here.setVisible(false);
|
||||||
|
mixedEnemies.setVisible(false);
|
||||||
|
enemySelector.setVisible(false);
|
||||||
|
count1Description.setVisible(false);
|
||||||
|
count2Description.setVisible(false);
|
||||||
|
count3Description.setVisible(false);
|
||||||
|
count1Spinner.setVisible(false);
|
||||||
|
count2Spinner.setVisible(false);
|
||||||
|
count3Spinner.setVisible(false);
|
||||||
|
poiPane.setVisible(false);
|
||||||
|
poiTokenLabel.setVisible(false);
|
||||||
|
nyi.setVisible(false);
|
||||||
|
}
|
||||||
|
private void switchPanels(){
|
||||||
|
hideAllControls();
|
||||||
|
if (objectiveType.getSelectedItem() == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch(objectiveType.getSelectedItem().toString()){
|
||||||
|
case "Arena":
|
||||||
|
arenaLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Clear":
|
||||||
|
clearLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
count1Description.setText("Target candidate percentile");
|
||||||
|
count1Description.setVisible(true);
|
||||||
|
count1Spinner.setVisible(true);
|
||||||
|
count2Description.setText("Percent variance");
|
||||||
|
count2Description.setVisible(true);
|
||||||
|
count2Spinner.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Defeat":
|
||||||
|
defeatLabel.setVisible(true);
|
||||||
|
mixedEnemies.setVisible(true);
|
||||||
|
count1Description.setText("Number to defeat");
|
||||||
|
count1Description.setVisible(true);
|
||||||
|
count1Spinner.setVisible(true);
|
||||||
|
count2Description.setText("Maximum losses");
|
||||||
|
count2Description.setVisible(true);
|
||||||
|
count2Spinner.setVisible(true);
|
||||||
|
enemySelector.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Delivery":
|
||||||
|
deliveryLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
deliveryItem.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Escort":
|
||||||
|
escortLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
spriteNames.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Fetch":
|
||||||
|
fetchLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
deliveryItem.setVisible(true);
|
||||||
|
enemySelector.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Find":
|
||||||
|
findLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Gather":
|
||||||
|
gatherLabel.setVisible(true);
|
||||||
|
gatherLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
itemNames.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Give":
|
||||||
|
giveLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
itemNames.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Hunt":
|
||||||
|
huntLabel.setVisible(true);
|
||||||
|
enemySelector.setVisible(true);
|
||||||
|
count1Description.setText("Lifespan (seconds to complete hunt before despawn)");
|
||||||
|
count1Description.setVisible(true);
|
||||||
|
count1Spinner.setVisible(true);
|
||||||
|
count1Spinner.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Leave":
|
||||||
|
leaveLabel.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "None":
|
||||||
|
noneLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Patrol":
|
||||||
|
patrolLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Rescue":
|
||||||
|
rescueLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
spriteNames.setVisible(true);
|
||||||
|
enemySelector.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Siege":
|
||||||
|
siegeLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
enemySelector.setVisible(true);
|
||||||
|
mixedEnemies.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "MapFlag":
|
||||||
|
mapFlagLabel.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
mapFlagGroup.setVisible(true);
|
||||||
|
flagValueGroup.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "QuestFlag":
|
||||||
|
nyi.setVisible(true);
|
||||||
|
questFlagLabel.setVisible(true);
|
||||||
|
mapFlagGroup.setVisible(true);
|
||||||
|
flagValueGroup.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Travel":
|
||||||
|
travelLabel.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
poiTokenInput.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
count1Description.setText("Target % of possible distances");
|
||||||
|
count1Description.setVisible(true);
|
||||||
|
count1Spinner.setVisible(true);
|
||||||
|
count2Description.setText("Plus or minus %");
|
||||||
|
count2Description.setVisible(true);
|
||||||
|
count2Spinner.setVisible(true);
|
||||||
|
break;
|
||||||
|
case "Use":
|
||||||
|
useLabel.setVisible(true);
|
||||||
|
nyi.setVisible(true);
|
||||||
|
itemNames.setVisible(true);
|
||||||
|
poiPane.setVisible(true);
|
||||||
|
anyPOI.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
poiTokenLabel.setVisible(true);
|
||||||
|
here.setVisible(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeObjective(){
|
||||||
|
if (objectiveType.getSelectedItem() != null)
|
||||||
|
currentData.objective = AdventureQuestController.ObjectiveTypes.valueOf(objectiveType.getSelectedItem().toString());
|
||||||
|
switchPanels();
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel getObjectiveTab(){
|
||||||
|
objectiveType = new JComboBox<>(AdventureQuestController.ObjectiveTypes.values());
|
||||||
|
objectiveType.addActionListener( e -> changeObjective());
|
||||||
|
|
||||||
|
JPanel objectiveTab = new JPanel();
|
||||||
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
|
objectiveTab.add(scrollPane);
|
||||||
|
FormPanel center=new FormPanel();
|
||||||
|
center.add(objectiveType);
|
||||||
|
scrollPane.add(center);
|
||||||
|
|
||||||
|
mapFlagGroup = new Box(BoxLayout.Y_AXIS);
|
||||||
|
mapFlagGroup.add(new JLabel("Map flag to check"));
|
||||||
|
mapFlagGroup.add(mapFlag);
|
||||||
|
|
||||||
|
flagValueGroup = new Box(BoxLayout.Y_AXIS);
|
||||||
|
flagValueGroup.add(new JLabel("Flag value to check"));
|
||||||
|
flagValueGroup.add(flagSpinner);
|
||||||
|
|
||||||
|
JPanel poiSelectorPane = new JPanel();
|
||||||
|
poiSelectorPane.setLayout(new BorderLayout());
|
||||||
|
poiSelectorPane.add(poiSelector, BorderLayout.CENTER);
|
||||||
|
JPanel poiTokenPanel = new JPanel();
|
||||||
|
|
||||||
|
JPanel tokenPanel = new JPanel();
|
||||||
|
tokenPanel.add(new JLabel("Token to use:"));
|
||||||
|
tokenPanel.add(poiTokenInput);
|
||||||
|
tokenPanel.setBorder(new EmptyBorder(10, 10, 30, 10));
|
||||||
|
|
||||||
|
poiTokenPanel.add(poiTokenDescription);
|
||||||
|
poiTokenPanel.add(tokenPanel);
|
||||||
|
poiTokenPanel.add(here);
|
||||||
|
|
||||||
|
GroupLayout poiTokenLayout = new GroupLayout(poiTokenPanel);
|
||||||
|
|
||||||
|
|
||||||
|
poiTokenLayout.setHorizontalGroup(
|
||||||
|
poiTokenLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(poiTokenDescription)
|
||||||
|
.addComponent(tokenPanel,GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
|
||||||
|
GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(here));
|
||||||
|
|
||||||
|
poiTokenLayout.setVerticalGroup(
|
||||||
|
poiTokenLayout.createSequentialGroup()
|
||||||
|
.addComponent(poiTokenDescription)
|
||||||
|
.addComponent(tokenPanel,GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
|
||||||
|
GroupLayout.PREFERRED_SIZE)
|
||||||
|
.addComponent(here));
|
||||||
|
|
||||||
|
poiTokenPanel.setLayout(poiTokenLayout);
|
||||||
|
|
||||||
|
poiPane.add("Specific PoI", poiTokenPanel);
|
||||||
|
poiPane.add("Tag Selector", poiSelectorPane);
|
||||||
|
poiPane.setPreferredSize(new Dimension(0,200));
|
||||||
|
|
||||||
|
|
||||||
|
center.add(arenaLabel);
|
||||||
|
center.add(clearLabel);
|
||||||
|
center.add(defeatLabel);
|
||||||
|
center.add(deliveryLabel);
|
||||||
|
center.add(escortLabel);
|
||||||
|
center.add(fetchLabel);
|
||||||
|
center.add(findLabel);
|
||||||
|
center.add(gatherLabel);
|
||||||
|
center.add(giveLabel);
|
||||||
|
center.add(huntLabel);
|
||||||
|
center.add(leaveLabel);
|
||||||
|
center.add(noneLabel);
|
||||||
|
center.add(patrolLabel);
|
||||||
|
center.add(rescueLabel);
|
||||||
|
center.add(siegeLabel);
|
||||||
|
center.add(mapFlagLabel);
|
||||||
|
center.add(questFlagLabel);
|
||||||
|
center.add(travelLabel);
|
||||||
|
center.add(useLabel);
|
||||||
|
center.add(nyi);
|
||||||
|
center.add(deliveryItem);
|
||||||
|
center.add(mapFlagGroup);
|
||||||
|
center.add(flagValueGroup);
|
||||||
|
center.add(anyPOI);
|
||||||
|
center.add(mixedEnemies);
|
||||||
|
center.add(enemySelector);
|
||||||
|
center.add(count1Description);
|
||||||
|
center.add(count1Spinner);
|
||||||
|
center.add(count2Description);
|
||||||
|
center.add(count2Spinner);
|
||||||
|
center.add(count3Description);
|
||||||
|
center.add(count3Spinner);
|
||||||
|
center.add(poiPane);
|
||||||
|
center.add(poiTokenLabel);
|
||||||
|
|
||||||
|
switchPanels();
|
||||||
|
|
||||||
|
poiSelector.selectedItems.addListDataListener(new ListDataListener() {
|
||||||
|
@Override
|
||||||
|
public void intervalAdded(ListDataEvent e) {
|
||||||
|
rebuildPOIList();
|
||||||
|
rebuildEnemyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void intervalRemoved(ListDataEvent e) {
|
||||||
|
rebuildPOIList();
|
||||||
|
rebuildEnemyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contentsChanged(ListDataEvent e) {
|
||||||
|
rebuildPOIList();
|
||||||
|
rebuildEnemyList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return center;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildPOIList(){
|
||||||
|
List<String> currentList = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int i = 0; i< poiSelector.selectedItems.getSize(); i++){
|
||||||
|
currentList.add(poiSelector.selectedItems.getElementAt(i));
|
||||||
|
}
|
||||||
|
currentData.POITags = currentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rebuildEnemyList(){
|
||||||
|
List<String> currentList = new ArrayList<>();
|
||||||
|
|
||||||
|
for(int i = 0; i< enemySelector.selectedItems.getSize(); i++){
|
||||||
|
currentList.add(enemySelector.selectedItems.getElementAt(i));
|
||||||
|
}
|
||||||
|
currentData.enemyTags = currentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JPanel getPrereqTab(){
|
||||||
|
JPanel prereqTab = new JPanel();
|
||||||
|
prereqTab.add(new JLabel("Insert Prereq data here"));
|
||||||
|
|
||||||
|
return prereqTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
|
||||||
|
if(currentData==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setEnabled(false);
|
||||||
|
updating=true;
|
||||||
|
objectiveType.setSelectedItem(currentData.objective);
|
||||||
|
if (objectiveType.getSelectedItem() != null)
|
||||||
|
currentData.objective = AdventureQuestController.ObjectiveTypes.valueOf(objectiveType.getSelectedItem().toString()); //Ensuring this gets initialized on new
|
||||||
|
|
||||||
|
name.setText(currentData.name);
|
||||||
|
description.setText(currentData.description);
|
||||||
|
deliveryItem.setText(currentData.deliveryItem);
|
||||||
|
|
||||||
|
if (currentData.enemyTags != null){
|
||||||
|
DefaultListModel<String> selectedEnemies = new DefaultListModel<>();
|
||||||
|
for (int i = 0; i < currentData.enemyTags.size(); i++) {
|
||||||
|
selectedEnemies.add(i, currentData.enemyTags.get(i));
|
||||||
|
}
|
||||||
|
enemySelector.load(selectedEnemies);
|
||||||
|
}
|
||||||
|
if (currentData.POITags != null){
|
||||||
|
DefaultListModel<String> selectedPOI = new DefaultListModel<>();
|
||||||
|
for (int i = 0; i < currentData.POITags.size(); i++) {
|
||||||
|
selectedPOI.add(i, currentData.POITags.get(i));
|
||||||
|
}
|
||||||
|
poiSelector.load(selectedPOI);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemNames.setText(currentData.itemNames);
|
||||||
|
equipNames.setText(currentData.equipNames);
|
||||||
|
prologueEditor.loadData(currentData.prologue);
|
||||||
|
epilogueEditor.loadData(currentData.epilogue);
|
||||||
|
|
||||||
|
|
||||||
|
if (currentData.POITags != null){
|
||||||
|
DefaultListModel<String> selectedPOI = new DefaultListModel<>();
|
||||||
|
for (int i = 0; i < currentData.POITags.size(); i++) {
|
||||||
|
selectedPOI.add(i, currentData.POITags.get(i));
|
||||||
|
}
|
||||||
|
poiSelector.load(selectedPOI);
|
||||||
|
}
|
||||||
|
here.getModel().setSelected(currentData.here);
|
||||||
|
poiTokenInput.setText(currentData.POIToken);
|
||||||
|
poiTokenLabel.setText( "To reference this point of interest: $(poi_" + currentData.id + ")");
|
||||||
|
|
||||||
|
ArrayList<String> temp = new ArrayList<>();
|
||||||
|
for (AdventureQuestStage stage : currentQuestData.stages){
|
||||||
|
if (stage.equals(currentData))
|
||||||
|
continue;
|
||||||
|
temp.add(stage.name);
|
||||||
|
}
|
||||||
|
prerequisites.setOptions(temp);
|
||||||
|
|
||||||
|
count1Spinner.getModel().setValue(currentData.count1);
|
||||||
|
count2Spinner.getModel().setValue(currentData.count2);
|
||||||
|
count3Spinner.getModel().setValue(currentData.count3);
|
||||||
|
|
||||||
|
updating=false;
|
||||||
|
setEnabled(true);
|
||||||
|
}
|
||||||
|
public void updateStage()
|
||||||
|
{
|
||||||
|
if(currentData==null||updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentData.name=name.getText();
|
||||||
|
currentData.description= description.getText();
|
||||||
|
currentData.prologue = prologueEditor.getDialogData();
|
||||||
|
currentData.epilogue = epilogueEditor.getDialogData();
|
||||||
|
currentData.deliveryItem = deliveryItem.getText();
|
||||||
|
currentData.itemNames = itemNames.getList()==null?new ArrayList<>():Arrays.asList(itemNames.getList());
|
||||||
|
currentData.equipNames = equipNames.getList()==null?new ArrayList<>():Arrays.asList(equipNames.getList());
|
||||||
|
currentData.anyPOI = anyPOI.getModel().isSelected();
|
||||||
|
currentData.mapFlag = mapFlag.getText();
|
||||||
|
currentData.mapFlagValue = Integer.parseInt(flagSpinner.getModel().getValue().toString());
|
||||||
|
currentData.count1 = Integer.parseInt(count1Spinner.getModel().getValue().toString());
|
||||||
|
currentData.count2 = Integer.parseInt(count2Spinner.getModel().getValue().toString());
|
||||||
|
currentData.count3 = Integer.parseInt(count3Spinner.getModel().getValue().toString());
|
||||||
|
currentData.mixedEnemies = mixedEnemies.getModel().isSelected();
|
||||||
|
currentData.here = here.getModel().isSelected();
|
||||||
|
currentData.POIToken = poiTokenInput.getText();
|
||||||
|
|
||||||
|
rebuildPOIList();
|
||||||
|
rebuildEnemyList();
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
public void setCurrentStage(AdventureQuestStage stageData, AdventureQuestData data) {
|
||||||
|
if (stageData == null)
|
||||||
|
stageData = new AdventureQuestStage();
|
||||||
|
if (data == null)
|
||||||
|
data = new AdventureQuestData();
|
||||||
|
currentData =stageData;
|
||||||
|
currentQuestData=data;
|
||||||
|
setVisible(true);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
protected void emitChanged() {
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addListeners(){
|
||||||
|
deliveryItem.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
mapFlag.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
flagSpinner.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
count1Spinner.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
count2Spinner.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
count3Spinner.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
mixedEnemies.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
here.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
anyPOI.getModel().addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
deliveryItem.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
mapFlag.getDocument().addDocumentListener(new DocumentChangeListener(QuestStageEdit.this::updateStage));
|
||||||
|
prologueEditor.addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
epilogueEditor.addChangeListener(q -> QuestStageEdit.this.updateStage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
|
import forge.adventure.data.AdventureQuestStage;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor class to edit configuration, maybe moved or removed
|
||||||
|
*/
|
||||||
|
public class QuestStageEditor extends JComponent{
|
||||||
|
DefaultListModel<AdventureQuestStage> model = new DefaultListModel<>();
|
||||||
|
JList<AdventureQuestStage> list = new JList<>(model);
|
||||||
|
JScrollPane scroll;
|
||||||
|
JToolBar toolBar = new JToolBar("toolbar");
|
||||||
|
QuestStageEdit edit=new QuestStageEdit();
|
||||||
|
|
||||||
|
AdventureQuestData currentData;
|
||||||
|
|
||||||
|
public class QuestStageRenderer extends DefaultListCellRenderer {
|
||||||
|
@Override
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean cellHasFocus) {
|
||||||
|
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||||
|
if(!(value instanceof AdventureQuestStage))
|
||||||
|
return label;
|
||||||
|
AdventureQuestStage stageData=(AdventureQuestStage) value;
|
||||||
|
label.setText(stageData.name);
|
||||||
|
//label.setIcon(new ImageIcon(Config.instance().getFilePath(stageData.sourcePath))); //Type icon eventually?
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void addButton(String name, ActionListener action)
|
||||||
|
{
|
||||||
|
JButton newButton=new JButton(name);
|
||||||
|
newButton.addActionListener(action);
|
||||||
|
toolBar.add(newButton);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuestStageEditor()
|
||||||
|
{
|
||||||
|
list.setCellRenderer(new QuestStageRenderer());
|
||||||
|
list.addListSelectionListener(e -> QuestStageEditor.this.updateEdit());
|
||||||
|
addButton("Add Quest Stage", e -> QuestStageEditor.this.addStage());
|
||||||
|
addButton("Remove Selected", e -> QuestStageEditor.this.remove());
|
||||||
|
toolBar.setFloatable(false);
|
||||||
|
setLayout(new BorderLayout());
|
||||||
|
scroll = new JScrollPane(list);
|
||||||
|
add(scroll, BorderLayout.WEST);
|
||||||
|
JPanel editPanel = new JPanel();
|
||||||
|
editPanel.setLayout(new BorderLayout());
|
||||||
|
add(toolBar, BorderLayout.NORTH);
|
||||||
|
editPanel.add(edit,BorderLayout.CENTER);
|
||||||
|
add(editPanel);
|
||||||
|
edit.addChangeListener(e -> emitChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void emitChanged() {
|
||||||
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEdit() {
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
edit.setCurrentStage(model.get(selected),currentData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addStage()
|
||||||
|
{
|
||||||
|
AdventureQuestStage data=new AdventureQuestStage();
|
||||||
|
data.name = "New Stage";
|
||||||
|
model.add(model.size(),data);
|
||||||
|
edit.setVisible(true);
|
||||||
|
scroll.setVisible(true);
|
||||||
|
int id = 0;
|
||||||
|
for (int i = 0; i < model.size(); i++)
|
||||||
|
{
|
||||||
|
if (model.get(i).id >= id)
|
||||||
|
id = model.get(i).id +1;
|
||||||
|
}
|
||||||
|
data.id = id;
|
||||||
|
if (model.size() == 1){
|
||||||
|
list.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
void remove()
|
||||||
|
{
|
||||||
|
int selected=list.getSelectedIndex();
|
||||||
|
if(selected<0)
|
||||||
|
return;
|
||||||
|
model.remove(selected);
|
||||||
|
edit.setVisible(false);
|
||||||
|
scroll.setVisible(list.getModel().getSize() > 0);
|
||||||
|
emitChanged();
|
||||||
|
}
|
||||||
|
public void setStages(AdventureQuestData data) {
|
||||||
|
|
||||||
|
currentData=data;
|
||||||
|
model.clear();
|
||||||
|
if(data==null||data.stages==null || data.stages.length == 0)
|
||||||
|
{
|
||||||
|
edit.setVisible(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i=0;i<data.stages.length;i++) {
|
||||||
|
model.add(i,data.stages[i]);
|
||||||
|
}
|
||||||
|
if (model.size() > 0) {
|
||||||
|
list.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestStage[] getStages() {
|
||||||
|
|
||||||
|
AdventureQuestStage[] stages= new AdventureQuestStage[model.getSize()];
|
||||||
|
for(int i=0;i<model.getSize();i++)
|
||||||
|
{
|
||||||
|
stages[i]=model.get(i);
|
||||||
|
}
|
||||||
|
return stages;
|
||||||
|
}
|
||||||
|
public void addChangeListener(ChangeListener listener) {
|
||||||
|
listenerList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package forge.adventure.editor;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class QuestTagSelector extends JComponent {
|
||||||
|
DefaultListModel<String> allItems = new DefaultListModel<>();
|
||||||
|
DefaultListModel<String> selectedItems = new DefaultListModel<>();
|
||||||
|
JList<String> unselectedList;
|
||||||
|
JList<String> selectedList;
|
||||||
|
|
||||||
|
boolean useEnemyTags = false;
|
||||||
|
boolean usePOITags = false;
|
||||||
|
|
||||||
|
public QuestTagSelector(String title, boolean useEnemyTags, boolean usePOITags)
|
||||||
|
{
|
||||||
|
if (useEnemyTags){
|
||||||
|
this.useEnemyTags = true;
|
||||||
|
} else if (usePOITags) {
|
||||||
|
this.usePOITags = true;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unselectedList = new JList<>(allItems);
|
||||||
|
selectedList = new JList<>(selectedItems);
|
||||||
|
// unselectedList.setCellRenderer(new PointOfInterestEditor.PointOfInterestRenderer()); // Replace with use count of tag?
|
||||||
|
// selectedList.setCellRenderer(new PointOfInterestEditor.PointOfInterestRenderer());
|
||||||
|
|
||||||
|
JButton addButton=new JButton("add");
|
||||||
|
JButton removeButton=new JButton("remove");
|
||||||
|
addButton.addActionListener( e -> QuestTagSelector.this.addTag());
|
||||||
|
removeButton.addActionListener( e -> QuestTagSelector.this.removeTag());
|
||||||
|
|
||||||
|
BorderLayout layout=new BorderLayout();
|
||||||
|
setLayout(layout);
|
||||||
|
if (title.length() > 0)
|
||||||
|
add(new JLabel(title),BorderLayout.PAGE_START);
|
||||||
|
add(new JScrollPane(unselectedList), BorderLayout.LINE_START);
|
||||||
|
add(new JScrollPane(selectedList), BorderLayout.LINE_END);
|
||||||
|
|
||||||
|
JPanel buttonPanel = new JPanel();
|
||||||
|
GridLayout buttonLayout = new GridLayout(2,0);
|
||||||
|
buttonPanel.setLayout(buttonLayout);
|
||||||
|
buttonPanel.add(addButton);
|
||||||
|
buttonPanel.add(removeButton);
|
||||||
|
add(buttonPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTag(){
|
||||||
|
if (unselectedList.isSelectionEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String toAdd : unselectedList.getSelectedValuesList())
|
||||||
|
{
|
||||||
|
if (selectedItems.contains(toAdd)) continue;
|
||||||
|
selectedItems.addElement(toAdd);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTag(){
|
||||||
|
if (selectedList.isSelectionEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String toRemove : selectedList.getSelectedValuesList())
|
||||||
|
{
|
||||||
|
selectedItems.removeElement(toRemove);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load(DefaultListModel<String> selectedNames)
|
||||||
|
{
|
||||||
|
allItems.clear();
|
||||||
|
selectedItems.clear();
|
||||||
|
|
||||||
|
if (useEnemyTags){
|
||||||
|
allItems = QuestController.getInstance().getEnemyTags(true);
|
||||||
|
}
|
||||||
|
else if (usePOITags) {
|
||||||
|
allItems = QuestController.getInstance().getPOITags(true);
|
||||||
|
}
|
||||||
|
unselectedList.setModel(allItems);
|
||||||
|
for (int i=0;i<allItems.size();i++){
|
||||||
|
if (selectedNames.contains(allItems.get(i))){
|
||||||
|
selectedItems.addElement(allItems.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean updating=false;
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
setEnabled(allItems!=null);
|
||||||
|
if(allItems==null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updating=true;
|
||||||
|
|
||||||
|
//unselectedList = new JList<>(allItems);
|
||||||
|
//selectedList = new JList<>(selectedItems);
|
||||||
|
updating=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ public class RewardsEditor extends JComponent{
|
|||||||
JList<RewardData> list = new JList<>(model);
|
JList<RewardData> list = new JList<>(model);
|
||||||
JToolBar toolBar = new JToolBar("toolbar");
|
JToolBar toolBar = new JToolBar("toolbar");
|
||||||
RewardEdit edit=new RewardEdit();
|
RewardEdit edit=new RewardEdit();
|
||||||
|
boolean updating;
|
||||||
|
|
||||||
|
|
||||||
public class RewardDataRenderer extends DefaultListCellRenderer {
|
public class RewardDataRenderer extends DefaultListCellRenderer {
|
||||||
@@ -67,14 +67,11 @@ public class RewardsEditor extends JComponent{
|
|||||||
add(edit,BorderLayout.CENTER);
|
add(edit,BorderLayout.CENTER);
|
||||||
|
|
||||||
|
|
||||||
edit.addChangeListener(new ChangeListener() {
|
edit.addChangeListener(e -> emitChanged());
|
||||||
@Override
|
|
||||||
public void stateChanged(ChangeEvent e) {
|
|
||||||
emitChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
protected void emitChanged() {
|
protected void emitChanged() {
|
||||||
|
if (updating)
|
||||||
|
return;
|
||||||
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
|
||||||
if (listeners != null && listeners.length > 0) {
|
if (listeners != null && listeners.length > 0) {
|
||||||
ChangeEvent evt = new ChangeEvent(this);
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
@@ -131,6 +128,12 @@ public class RewardsEditor extends JComponent{
|
|||||||
}
|
}
|
||||||
return rewards;
|
return rewards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear(){
|
||||||
|
updating = true;
|
||||||
|
model.clear();
|
||||||
|
updating = false;
|
||||||
|
}
|
||||||
public void addChangeListener(ChangeListener listener) {
|
public void addChangeListener(ChangeListener listener) {
|
||||||
listenerList.add(ChangeListener.class, listener);
|
listenerList.add(ChangeListener.class, listener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class SwingAtlasPreview extends Box {
|
|||||||
Timer timer;
|
Timer timer;
|
||||||
public SwingAtlasPreview()
|
public SwingAtlasPreview()
|
||||||
{
|
{
|
||||||
this(32,200);
|
this(64,200);
|
||||||
}
|
}
|
||||||
public SwingAtlasPreview(int imageSize,int timeDelay) {
|
public SwingAtlasPreview(int imageSize,int timeDelay) {
|
||||||
super(BoxLayout.Y_AXIS);
|
super(BoxLayout.Y_AXIS);
|
||||||
@@ -47,7 +47,7 @@ public class SwingAtlasPreview extends Box {
|
|||||||
setSpritePath(sprite,null);
|
setSpritePath(sprite,null);
|
||||||
}
|
}
|
||||||
public void setSpritePath(String sprite,String name) {
|
public void setSpritePath(String sprite,String name) {
|
||||||
if(this.sprite==null||sprite==null||(this.sprite.equals(sprite)&&(spriteName!=null&&name!=null&&spriteName.equals(name))))
|
if(this.sprite==null||sprite==null||(this.sprite.equals(sprite)&&(spriteName != null && spriteName.equals(name))))
|
||||||
return;
|
return;
|
||||||
removeAll();
|
removeAll();
|
||||||
counter=0;
|
counter=0;
|
||||||
@@ -85,10 +85,10 @@ public class SwingAtlasPreview extends Box {
|
|||||||
{
|
{
|
||||||
timer.restart();
|
timer.restart();
|
||||||
}
|
}
|
||||||
doLayout();
|
// doLayout(); //These lines cause images to bleed on to other tabs and don't appear to be needed
|
||||||
revalidate();
|
// revalidate();
|
||||||
update(getGraphics());
|
// update(getGraphics());
|
||||||
repaint();
|
// repaint();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,7 @@
|
|||||||
package forge.adventure.editor;
|
package forge.adventure.editor;
|
||||||
|
|
||||||
import forge.adventure.util.Config;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,16 +14,11 @@ public class TextListEdit extends Box {
|
|||||||
public TextListEdit(String[] possibleElements) {
|
public TextListEdit(String[] possibleElements) {
|
||||||
super(BoxLayout.X_AXIS);
|
super(BoxLayout.X_AXIS);
|
||||||
|
|
||||||
findButton.addActionListener(new ActionListener() {
|
findButton.addActionListener(e -> TextListEdit.this.find());
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
TextListEdit.this.find();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add(edit);
|
add(edit);
|
||||||
edit.setPreferredSize(new Dimension(400,edit.getPreferredSize().height));
|
edit.setPreferredSize(new Dimension(400,edit.getPreferredSize().height));
|
||||||
//add(findButton);
|
add(findButton);
|
||||||
elements= new JComboBox(possibleElements);
|
elements= new JComboBox(possibleElements);
|
||||||
add(elements);
|
add(elements);
|
||||||
|
|
||||||
@@ -45,20 +34,32 @@ public class TextListEdit extends Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void find() {
|
private void find() {
|
||||||
JFileChooser fc = new JFileChooser();
|
edit.setText((edit.getText().trim().length()>0?edit.getText() + ";": "")+elements.getSelectedItem().toString());
|
||||||
fc.setCurrentDirectory(new File(Config.instance().getFilePath("")));
|
elements.remove(elements.getSelectedIndex());
|
||||||
fc.setMultiSelectionEnabled(false);
|
elements.setSelectedIndex(0);
|
||||||
if (fc.showOpenDialog(this) ==
|
// JFileChooser fc = new JFileChooser();
|
||||||
JFileChooser.APPROVE_OPTION) {
|
// fc.setCurrentDirectory(new File(Config.instance().getFilePath("")));
|
||||||
File selected = fc.getSelectedFile();
|
// fc.setMultiSelectionEnabled(false);
|
||||||
|
// if (fc.showOpenDialog(this) ==
|
||||||
|
// JFileChooser.APPROVE_OPTION) {
|
||||||
|
// File selected = fc.getSelectedFile();
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// if (selected != null&&selected.getCanonicalPath().startsWith(new File(Config.instance().getFilePath("")).getCanonicalPath())) {
|
||||||
|
// edit.setText(selected.getCanonicalPath().substring(new File(Config.instance().getFilePath("")).getCanonicalPath().length()+1));
|
||||||
|
// }
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
public void setOptions(List<String> itemNames) {
|
||||||
if (selected != null&&selected.getCanonicalPath().startsWith(new File(Config.instance().getFilePath("")).getCanonicalPath())) {
|
if(itemNames==null)
|
||||||
edit.setText(selected.getCanonicalPath().substring(new File(Config.instance().getFilePath("")).getCanonicalPath().length()+1));
|
elements.removeAllItems();
|
||||||
}
|
else {
|
||||||
} catch (IOException e) {
|
for(String item: itemNames)
|
||||||
e.printStackTrace();
|
elements.addItem(item);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ public class TextListEdit extends Box {
|
|||||||
String intName=stringList[i];
|
String intName=stringList[i];
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
retList[i] = Integer.valueOf(intName);
|
retList[i] = Integer.parseInt(intName);
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1023,8 +1023,11 @@ public class Forge implements ApplicationListener {
|
|||||||
return ((Forge)Gdx.app.getApplicationListener()).assets;
|
return ((Forge)Gdx.app.getApplicationListener()).assets;
|
||||||
}
|
}
|
||||||
public static boolean switchScene(Scene newScene) {
|
public static boolean switchScene(Scene newScene) {
|
||||||
if (newScene instanceof RewardScene || newScene instanceof SpellSmithScene || newScene instanceof DeckSelectScene || newScene instanceof PlayerStatisticScene) {
|
return switchScene(newScene, false);
|
||||||
if (!(currentScene instanceof ForgeScene)) //prevent overwriting the last preview if last scene is instance of ForgeScene
|
}
|
||||||
|
public static boolean switchScene(Scene newScene, boolean skipPreview) {
|
||||||
|
if (newScene instanceof RewardScene || newScene instanceof SpellSmithScene || newScene instanceof DeckSelectScene || newScene instanceof PlayerStatisticScene || newScene instanceof QuestLogScene) {
|
||||||
|
if (!(currentScene instanceof ForgeScene || skipPreview)) //prevent overwriting the last preview if last scene is instance of ForgeScene
|
||||||
WorldSave.getCurrentSave().header.createPreview();
|
WorldSave.getCurrentSave().header.createPreview();
|
||||||
}
|
}
|
||||||
if (currentScene != null) {
|
if (currentScene != null) {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package forge.adventure.character;
|
|||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
import forge.adventure.stage.MapStage;
|
import forge.adventure.stage.MapStage;
|
||||||
|
import forge.adventure.util.Current;
|
||||||
import forge.adventure.util.MapDialog;
|
import forge.adventure.util.MapDialog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +13,8 @@ import forge.adventure.util.MapDialog;
|
|||||||
public class DialogActor extends CharacterSprite {
|
public class DialogActor extends CharacterSprite {
|
||||||
private final MapStage stage;
|
private final MapStage stage;
|
||||||
private final TextureRegion textureRegion;
|
private final TextureRegion textureRegion;
|
||||||
private final MapDialog dialog;
|
private MapDialog dialog;
|
||||||
|
public AdventureQuestData questData;
|
||||||
|
|
||||||
public DialogActor(MapStage stage, int id, String S, TextureRegion textureRegion) {
|
public DialogActor(MapStage stage, int id, String S, TextureRegion textureRegion) {
|
||||||
super(id,"");
|
super(id,"");
|
||||||
@@ -26,6 +29,19 @@ public class DialogActor extends CharacterSprite {
|
|||||||
this.textureRegion = null;
|
this.textureRegion = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DialogActor(AdventureQuestData data, MapStage stage, int id){
|
||||||
|
super(id,"");
|
||||||
|
this.stage = stage;
|
||||||
|
dialog = new MapDialog(data.offerDialog, stage, id);
|
||||||
|
this.textureRegion = null;
|
||||||
|
this.questData = data;
|
||||||
|
dialog.addQuestAcceptedListener(e -> acceptQuest());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acceptQuest(){
|
||||||
|
Current.player().addQuest(questData);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerCollide() {
|
public void onPlayerCollide() {
|
||||||
stage.resetPosition();
|
stage.resetPosition();
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ import forge.adventure.data.EffectData;
|
|||||||
import forge.adventure.data.EnemyData;
|
import forge.adventure.data.EnemyData;
|
||||||
import forge.adventure.data.RewardData;
|
import forge.adventure.data.RewardData;
|
||||||
import forge.adventure.player.AdventurePlayer;
|
import forge.adventure.player.AdventurePlayer;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterestChanges;
|
||||||
import forge.adventure.util.Current;
|
import forge.adventure.util.Current;
|
||||||
import forge.adventure.util.MapDialog;
|
import forge.adventure.util.MapDialog;
|
||||||
import forge.adventure.util.Reward;
|
import forge.adventure.util.Reward;
|
||||||
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
@@ -54,6 +56,8 @@ public class EnemySprite extends CharacterSprite {
|
|||||||
public float threatRange = 0.0f;
|
public float threatRange = 0.0f;
|
||||||
public float fleeRange = 0.0f;
|
public float fleeRange = 0.0f;
|
||||||
public boolean ignoreDungeonEffect = false;
|
public boolean ignoreDungeonEffect = false;
|
||||||
|
private PointOfInterestChanges changes;
|
||||||
|
public float spawnDelay;
|
||||||
|
|
||||||
public EnemySprite(EnemyData enemyData) {
|
public EnemySprite(EnemyData enemyData) {
|
||||||
this(0,enemyData);
|
this(0,enemyData);
|
||||||
@@ -64,6 +68,12 @@ public class EnemySprite extends CharacterSprite {
|
|||||||
data = enemyData;
|
data = enemyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EnemySprite(int id, EnemyData enemyData, PointOfInterestChanges changes) {
|
||||||
|
super(id,enemyData.sprite);
|
||||||
|
data = enemyData;
|
||||||
|
this.changes = changes;
|
||||||
|
}
|
||||||
|
|
||||||
public void parseWaypoints(String waypoints){
|
public void parseWaypoints(String waypoints){
|
||||||
String[] wp = waypoints.replaceAll("\\s", "").split(",");
|
String[] wp = waypoints.replaceAll("\\s", "").split(",");
|
||||||
for (String s : wp) {
|
for (String s : wp) {
|
||||||
@@ -106,6 +116,7 @@ public class EnemySprite extends CharacterSprite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Vector2 getTargetVector(PlayerSprite player, float delta) {
|
public Vector2 getTargetVector(PlayerSprite player, float delta) {
|
||||||
|
//todo - this can be integrated into overworld movement as well, giving flee behaviors or moving to generated waypoints
|
||||||
Vector2 target = pos();
|
Vector2 target = pos();
|
||||||
Vector2 routeToPlayer = new Vector2(player.pos()).sub(target);
|
Vector2 routeToPlayer = new Vector2(player.pos()).sub(target);
|
||||||
|
|
||||||
@@ -227,14 +238,25 @@ public class EnemySprite extends CharacterSprite {
|
|||||||
Deck enemyDeck = Current.latestDeck();
|
Deck enemyDeck = Current.latestDeck();
|
||||||
/*// By popular demand, remove basic lands from the reward pool.
|
/*// By popular demand, remove basic lands from the reward pool.
|
||||||
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND), PaperCard.FN_GET_RULES));*/
|
CardPool deckNoBasicLands = enemyDeck.getMain().getFilteredPool(Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND), PaperCard.FN_GET_RULES));*/
|
||||||
|
if (changes!=null){
|
||||||
|
long shopSeed = changes.getShopSeed(objectId);
|
||||||
|
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(shopSeed);
|
||||||
|
}
|
||||||
|
|
||||||
for (RewardData rdata : data.rewards) {
|
for (RewardData rdata : data.rewards) {
|
||||||
ret.addAll(rdata.generate(false, enemyDeck == null ? null : enemyDeck.getMain().toFlatList() ));
|
ret.addAll(rdata.generate(false, enemyDeck == null ? null : enemyDeck.getMain().toFlatList(),true ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(rewards != null) { //Collect additional rewards.
|
if(rewards != null) { //Collect additional rewards.
|
||||||
for(RewardData rdata:rewards) {
|
for(RewardData rdata:rewards) {
|
||||||
//Do not filter in case we want to FORCE basic lands. If it ever becomes a problem just repeat the same as above.
|
//Do not filter in case we want to FORCE basic lands. If it ever becomes a problem just repeat the same as above.
|
||||||
ret.addAll(rdata.generate(false,(Current.latestDeck() != null ? Current.latestDeck().getMain().toFlatList() : null)));
|
if (changes != null)
|
||||||
|
{
|
||||||
|
long shopSeed = changes.getShopSeed(objectId);
|
||||||
|
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(shopSeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.addAll(rdata.generate(false,(Current.latestDeck() != null ? Current.latestDeck().getMain().toFlatList() : null), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,8 +329,21 @@ public class EnemySprite extends CharacterSprite {
|
|||||||
return data.speed;
|
return data.speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float getLifetime() {
|
||||||
|
//default and minimum value for time to remain on overworld map
|
||||||
|
Float lifetime = 20f;
|
||||||
|
return Math.max(data.lifetime, lifetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class MovementBehavior {
|
public class MovementBehavior {
|
||||||
|
|
||||||
|
//temporary placeholders for overworld behavior integration
|
||||||
|
public boolean wander = false;
|
||||||
|
public boolean flee = false;
|
||||||
|
public boolean stop = false;
|
||||||
|
//end temporary
|
||||||
|
|
||||||
float duration = 0.0f;
|
float duration = 0.0f;
|
||||||
float x = 0.0f;
|
float x = 0.0f;
|
||||||
float y = 0.0f;
|
float y = 0.0f;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class RewardSprite extends CharacterSprite {
|
|||||||
Array<Reward> ret = new Array<Reward>();
|
Array<Reward> ret = new Array<Reward>();
|
||||||
if(rewards == null) return ret;
|
if(rewards == null) return ret;
|
||||||
for(RewardData rdata:rewards) {
|
for(RewardData rdata:rewards) {
|
||||||
ret.addAll(rdata.generate(false));
|
ret.addAll(rdata.generate(false, true));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,416 @@
|
|||||||
|
package forge.adventure.data;
|
||||||
|
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import forge.adventure.character.EnemySprite;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterest;
|
||||||
|
import forge.adventure.scene.GameScene;
|
||||||
|
import forge.adventure.util.AdventureQuestController;
|
||||||
|
import forge.adventure.util.Current;
|
||||||
|
import forge.adventure.world.WorldSave;
|
||||||
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
public class AdventureQuestData implements Serializable {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
public int getID(){
|
||||||
|
if (isTemplate && id < 1)
|
||||||
|
id = Current.world().getNextQuestId();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
public boolean isTemplate = false;
|
||||||
|
public String name = "";
|
||||||
|
public String description = "";
|
||||||
|
public String synopsis =""; //Intended for Dev Mode only at most
|
||||||
|
public transient boolean completed = false;
|
||||||
|
public transient boolean failed = false;
|
||||||
|
private transient boolean prologueDisplayed = false;
|
||||||
|
private transient boolean epilogueDisplayed = false;
|
||||||
|
|
||||||
|
public DialogData offerDialog;
|
||||||
|
public DialogData prologue;
|
||||||
|
public DialogData epilogue;
|
||||||
|
public DialogData failureDialog;
|
||||||
|
|
||||||
|
public DialogData declinedDialog;
|
||||||
|
|
||||||
|
public RewardData reward;
|
||||||
|
public String rewardDescription = "";
|
||||||
|
|
||||||
|
public AdventureQuestStage[] stages = new AdventureQuestStage[0];
|
||||||
|
public String[] questTags = new String[0];
|
||||||
|
public String[] questEnemyTags = new String[0];
|
||||||
|
public String[] questPOITags = new String[0];
|
||||||
|
private transient EnemySprite targetEnemySprite = null;
|
||||||
|
private PointOfInterest targetPoI = null;
|
||||||
|
Dictionary<String, PointOfInterest> poiTokens = new Hashtable<>();
|
||||||
|
Dictionary<String, EnemyData> enemyTokens = new Hashtable<>();
|
||||||
|
Dictionary<String, String> otherTokens = new Hashtable<>();
|
||||||
|
public boolean storyQuest = false;
|
||||||
|
public transient boolean isTracked = false;
|
||||||
|
public String sourceID = "";
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
public RewardData getReward() {
|
||||||
|
return reward;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestData(AdventureQuestData data){
|
||||||
|
id = data.id;
|
||||||
|
isTemplate = false; //Anything being copied is by definition not a template
|
||||||
|
name = data.name;
|
||||||
|
description = data.description;
|
||||||
|
synopsis = data.synopsis;
|
||||||
|
offerDialog = new DialogData(data.offerDialog);
|
||||||
|
prologue = new DialogData(data.prologue);
|
||||||
|
epilogue = new DialogData(data.epilogue);
|
||||||
|
failureDialog = new DialogData(data.failureDialog);
|
||||||
|
declinedDialog = new DialogData(data.declinedDialog);
|
||||||
|
reward = new RewardData(data.reward);
|
||||||
|
rewardDescription = data.rewardDescription;
|
||||||
|
completed = data.completed;
|
||||||
|
stages = new AdventureQuestStage[data.stages.length];
|
||||||
|
for (int i = 0; i < stages.length; i++){
|
||||||
|
stages[i] = new AdventureQuestStage(data.stages[i]);
|
||||||
|
}
|
||||||
|
questTags = data.questTags.clone();
|
||||||
|
questPOITags = data.questPOITags.clone();
|
||||||
|
questEnemyTags = data.questEnemyTags.clone();
|
||||||
|
targetPoI = data.targetPoI;
|
||||||
|
targetEnemySprite = data.targetEnemySprite;
|
||||||
|
storyQuest = data.storyQuest;
|
||||||
|
sourceID = data.sourceID;
|
||||||
|
poiTokens = data.poiTokens;
|
||||||
|
enemyTokens = data.enemyTokens;
|
||||||
|
otherTokens = data.otherTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestData()
|
||||||
|
{
|
||||||
|
declinedDialog = new DialogData();
|
||||||
|
declinedDialog.text = "Come back tomorrow and perhaps I'll have something that you'll actually be willing to do.";
|
||||||
|
DialogData dismiss = new DialogData();
|
||||||
|
dismiss.name = "(Catching the not so subtle hint, you leave.)";
|
||||||
|
declinedDialog.options = new DialogData[1];
|
||||||
|
declinedDialog.options[0] = dismiss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AdventureQuestStage> getActiveStages(){
|
||||||
|
List<AdventureQuestStage> toReturn = new ArrayList<>();
|
||||||
|
|
||||||
|
//Temporarily allow only one active stage until parallel stages and prerequisites are implemented
|
||||||
|
for (AdventureQuestStage stage : stages) {
|
||||||
|
if (stage.getStatus() == AdventureQuestController.QuestStatus.Complete)
|
||||||
|
continue;
|
||||||
|
if (stage.getStatus() == AdventureQuestController.QuestStatus.Inactive ) {
|
||||||
|
//todo: check prerequisites instead of break statement below
|
||||||
|
stage.setStatus(AdventureQuestController.QuestStatus.Active);
|
||||||
|
}
|
||||||
|
toReturn.add(stage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AdventureQuestStage> getStagesForQuestLog(){
|
||||||
|
List<AdventureQuestStage> toReturn = new ArrayList<>();
|
||||||
|
|
||||||
|
//Temporarily allow only one active stage until parallel stages and prerequisites are implemented
|
||||||
|
for (AdventureQuestStage stage : stages) {
|
||||||
|
if (stage.getStatus() == AdventureQuestController.QuestStatus.Complete
|
||||||
|
|| stage.getStatus() == AdventureQuestController.QuestStatus.Failed)
|
||||||
|
{
|
||||||
|
toReturn.add(stage);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
toReturn.add(stage);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PointOfInterest getTargetPOI() {
|
||||||
|
|
||||||
|
for (AdventureQuestStage stage : getActiveStages()) {
|
||||||
|
targetPoI = stage.getTargetPOI();
|
||||||
|
if (targetPoI != null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return targetPoI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnemySprite getTargetEnemySprite(){
|
||||||
|
if (targetEnemySprite == null){
|
||||||
|
for (AdventureQuestStage stage : getActiveStages()) {
|
||||||
|
targetEnemySprite = stage.getTargetSprite();
|
||||||
|
if (targetEnemySprite != null){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return targetEnemySprite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(){
|
||||||
|
for (AdventureQuestStage stage : stages){
|
||||||
|
initializeStage(stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceTokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeStage(AdventureQuestStage stage){
|
||||||
|
if (stage == null || stage.objective == null) return;
|
||||||
|
|
||||||
|
switch (stage.objective){
|
||||||
|
case Clear:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
break;
|
||||||
|
case Defeat:
|
||||||
|
if (!stage.mixedEnemies)
|
||||||
|
stage.setTargetEnemyData(generateTargetEnemyData(stage));
|
||||||
|
break;
|
||||||
|
case Delivery:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
//Set delivery item as a miscellaneous token
|
||||||
|
break;
|
||||||
|
case Escort:
|
||||||
|
//add configuration of what is being escorted.
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
if (!stage.mixedEnemies)
|
||||||
|
stage.setTargetEnemyData(generateTargetEnemyData(stage));
|
||||||
|
break;
|
||||||
|
case Hunt:
|
||||||
|
stage.setTargetSprite(generateTargetEnemySprite(stage));
|
||||||
|
break;
|
||||||
|
case Leave:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
break;
|
||||||
|
case MapFlag:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
break;
|
||||||
|
case Patrol:
|
||||||
|
//Need ability to set a series of target coordinates that can be reached, point nav arrow to them
|
||||||
|
// This might get oddly complex.
|
||||||
|
break;
|
||||||
|
case Rescue:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
break;
|
||||||
|
case Travel:
|
||||||
|
stage.setTargetPOI(poiTokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage.getTargetPOI() != null
|
||||||
|
&& ("cave".equalsIgnoreCase( stage.getTargetPOI().getData().type)
|
||||||
|
|| "dungeon".equalsIgnoreCase( stage.getTargetPOI().getData().type))){
|
||||||
|
//todo: decide how to handle this in "anyPOI" scenarios
|
||||||
|
WorldSave.getCurrentSave().getPointOfInterestChanges(stage.getTargetPOI().getID() + stage.getTargetPOI().getData().map).clearDeletedObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
PointOfInterest temp = stage.getTargetPOI();
|
||||||
|
if (temp != null)
|
||||||
|
poiTokens.put("$(poi_" + stage.id+")", temp);
|
||||||
|
|
||||||
|
EnemyData target = stage.getTargetEnemyData();
|
||||||
|
if (target != null)
|
||||||
|
enemyTokens.put("$(enemy_" + stage.id +")", target);
|
||||||
|
|
||||||
|
otherTokens.put("$(playername)", Current.player().getName());
|
||||||
|
otherTokens.put("$(currentbiome)", GameScene.instance().getAdventurePlayerLocation(true,false));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void replaceTokens(){
|
||||||
|
replaceTokens(offerDialog);
|
||||||
|
replaceTokens(prologue);
|
||||||
|
replaceTokens(epilogue);
|
||||||
|
replaceTokens(failureDialog);
|
||||||
|
replaceTokens(declinedDialog);
|
||||||
|
|
||||||
|
name = replaceTokens(name);
|
||||||
|
description = replaceTokens(description);
|
||||||
|
rewardDescription = replaceTokens(rewardDescription);
|
||||||
|
|
||||||
|
for (AdventureQuestStage stage: stages)
|
||||||
|
{
|
||||||
|
replaceTokens(stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceTokens(AdventureQuestStage stage){
|
||||||
|
replaceTokens(stage.prologue);
|
||||||
|
replaceTokens(stage.epilogue);
|
||||||
|
replaceTokens(stage.failureDialog);
|
||||||
|
stage.name = replaceTokens(stage.name);
|
||||||
|
stage.description = replaceTokens(stage.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String replaceTokens(String data){
|
||||||
|
for (Enumeration<String> e = poiTokens.keys(); e.hasMoreElements();){
|
||||||
|
String key = e.nextElement();
|
||||||
|
data = data.replace(key, poiTokens.get(key).getData().name);
|
||||||
|
}
|
||||||
|
for (Enumeration<String> enemy = enemyTokens.keys(); enemy.hasMoreElements();){
|
||||||
|
String enemyKey = enemy.nextElement();
|
||||||
|
data = data.replace(enemyKey, enemyTokens.get(enemyKey).getName());
|
||||||
|
}
|
||||||
|
for (Enumeration<String> other = otherTokens.keys(); other.hasMoreElements();){
|
||||||
|
String key = other.nextElement();
|
||||||
|
data = data.replace(key, otherTokens.get(key));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replaceTokens(DialogData data){
|
||||||
|
for (DialogData option : data.options){
|
||||||
|
replaceTokens(option);
|
||||||
|
}
|
||||||
|
for (Enumeration<String> e = poiTokens.keys(); e.hasMoreElements();){
|
||||||
|
String key = e.nextElement();
|
||||||
|
data.text = data.text.replace(key, poiTokens.get(key).getData().name);
|
||||||
|
data.name = data.name.replace(key, poiTokens.get(key).getData().name);
|
||||||
|
}
|
||||||
|
for (Enumeration<String> e = enemyTokens.keys(); e.hasMoreElements();){
|
||||||
|
String key = e.nextElement();
|
||||||
|
data.text = data.text.replace(key, enemyTokens.get(key).getName());
|
||||||
|
data.name = data.name.replace(key, enemyTokens.get(key).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Enumeration<String> other = otherTokens.keys(); other.hasMoreElements();){
|
||||||
|
String key = other.nextElement();
|
||||||
|
data.text = data.text.replace(key, otherTokens.get(key));
|
||||||
|
data.name = data.name.replace(key, otherTokens.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DialogData.ActionData ad: data.action) {
|
||||||
|
if ( ad != null && ad.POIReference != null)
|
||||||
|
{
|
||||||
|
for (Enumeration<String> e = poiTokens.keys(); e.hasMoreElements(); ) {
|
||||||
|
String key = e.nextElement();
|
||||||
|
ad.POIReference = ad.POIReference.replace(key, poiTokens.get(key).getID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnemySprite generateTargetEnemySprite(AdventureQuestStage stage){
|
||||||
|
if (stage.objective == AdventureQuestController.ObjectiveTypes.Hunt){
|
||||||
|
EnemyData toUse = generateTargetEnemyData(stage);
|
||||||
|
toUse.lifetime = stage.count1;
|
||||||
|
return new EnemySprite(toUse);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EnemyData generateTargetEnemyData(AdventureQuestStage stage)
|
||||||
|
{
|
||||||
|
ArrayList<EnemyData> matchesTags = new ArrayList<>();
|
||||||
|
for(EnemyData data: new Array.ArrayIterator<>(WorldData.getAllEnemies())) {
|
||||||
|
boolean valid = true;
|
||||||
|
for (String tag : stage.enemyTags) {
|
||||||
|
if (!Arrays.asList(data.questTags).contains(tag)) {
|
||||||
|
valid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (valid)
|
||||||
|
matchesTags.add(data);
|
||||||
|
}
|
||||||
|
if (matchesTags.isEmpty()){
|
||||||
|
return new EnemyData(Aggregates.random(WorldData.getAllEnemies()));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return new EnemyData(Aggregates.random(matchesTags));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEnteredPOI(PointOfInterest arrivedAt){
|
||||||
|
boolean done = true;
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
|
||||||
|
done = stage.updateEnterPOI(arrivedAt) == AdventureQuestController.QuestStatus.Complete && done;
|
||||||
|
if (!done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
completed = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMapFlag(String questFlag, int flagValue){
|
||||||
|
boolean done = true;
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
done = stage.updateMapFlag(questFlag, flagValue) == AdventureQuestController.QuestStatus.Complete && done;
|
||||||
|
if (!done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
completed = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLeave(){
|
||||||
|
boolean done = true;
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
done = stage.updateLeave() == AdventureQuestController.QuestStatus.Complete && done;
|
||||||
|
if (!done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
completed = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateWin(EnemySprite defeated, boolean cleared){
|
||||||
|
boolean done = true;
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
done = stage.updateWin(defeated, cleared) == AdventureQuestController.QuestStatus.Complete && done;
|
||||||
|
if (!done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
completed = done;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLose(EnemySprite defeatedBy){
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
if(failed)
|
||||||
|
break;
|
||||||
|
failed = stage.updateLose(defeatedBy) == AdventureQuestController.QuestStatus.Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDespawn(EnemySprite despawned){
|
||||||
|
for (AdventureQuestStage stage: stages) {
|
||||||
|
failed = stage.updateDespawn(despawned)== AdventureQuestController.QuestStatus.Failed || failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData getPrologue() {
|
||||||
|
if (!prologueDisplayed) {
|
||||||
|
prologueDisplayed = true;
|
||||||
|
return prologue;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogData getEpilogue() {
|
||||||
|
if (!epilogueDisplayed) {
|
||||||
|
epilogueDisplayed = true;
|
||||||
|
return epilogue;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fail(){
|
||||||
|
failed = true;
|
||||||
|
isTracked = false;
|
||||||
|
//todo: handle any necessary cleanup or reputation loss
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,307 @@
|
|||||||
|
package forge.adventure.data;
|
||||||
|
|
||||||
|
import forge.adventure.character.EnemySprite;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterest;
|
||||||
|
import forge.adventure.util.AdventureQuestController;
|
||||||
|
import forge.adventure.util.Current;
|
||||||
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class AdventureQuestStage implements Serializable {
|
||||||
|
public int id;
|
||||||
|
private AdventureQuestController.QuestStatus status = AdventureQuestController.QuestStatus.Inactive;
|
||||||
|
public String name = "";
|
||||||
|
public String description = "";
|
||||||
|
public boolean anyPOI = false; //false: Pick one PoI. True: Any PoI matching tags is usable
|
||||||
|
public String mapFlag; //Map (or quest) flag to check
|
||||||
|
public int mapFlagValue; //Minimum value for the flag
|
||||||
|
public int count1; //use defined by objective type, this can be enemies to defeat, minimum PoI distance, etc
|
||||||
|
public int count2; //use defined by objective type, this can be enemies to defeat, minimum PoI distance, etc
|
||||||
|
public int count3; //use defined by objective type, this can be enemies to defeat, minimum PoI distance, etc
|
||||||
|
private int progress1; //Progress toward count1
|
||||||
|
private int progress2; //Progress toward count2
|
||||||
|
private int progress3; //Progress toward count3
|
||||||
|
public boolean mixedEnemies; //false: Pick one enemy type. True: Combine all potential types
|
||||||
|
public boolean here; //Default PoI selection to current location
|
||||||
|
private PointOfInterest targetPOI; //Destination. Expand to array to cover "anyPOI?"
|
||||||
|
private transient EnemySprite targetSprite; //EnemySprite targeted by this quest stage.
|
||||||
|
private EnemyData targetEnemyData; //Valid enemy type for this quest stage when mixedEnemies is false.
|
||||||
|
public List<String> POITags = new ArrayList<>(); //Tags defining potential targets
|
||||||
|
public AdventureQuestController.ObjectiveTypes objective;
|
||||||
|
public List<String> prerequisiteNames = new ArrayList<>();
|
||||||
|
public List<String> enemyTags = new ArrayList<>(); //Tags defining potential targets
|
||||||
|
public List<String> itemNames = new ArrayList<>(); //Tags defining items to use
|
||||||
|
public List<String> equipNames = new ArrayList<>(); //Tags defining equipment to use
|
||||||
|
public boolean prologueDisplayed = false;
|
||||||
|
public boolean epilogueDisplayed = false;
|
||||||
|
public DialogData prologue;
|
||||||
|
public DialogData epilogue;
|
||||||
|
public DialogData failureDialog;
|
||||||
|
public boolean prequisitesComplete = false;
|
||||||
|
public String deliveryItem = ""; //Imaginary item to get/fetch/deliver. Could be a general purpose field.
|
||||||
|
public String POIToken; //If defined, ignore tags input and use the target POI from a different stage's objective instead.
|
||||||
|
private transient boolean inTargetLocation = false;
|
||||||
|
|
||||||
|
public void checkPrerequisites() {
|
||||||
|
//Todo - implement
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus getStatus(){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(AdventureQuestController.QuestStatus newStatus){
|
||||||
|
if (!status.equals(newStatus) && newStatus.equals(AdventureQuestController.QuestStatus.Active)){
|
||||||
|
AdventureQuestController.instance().addQuestSprites(this);
|
||||||
|
}
|
||||||
|
status = newStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PointOfInterest getTargetPOI() {
|
||||||
|
return targetPOI;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetPOI(PointOfInterest target) {
|
||||||
|
if (!anyPOI)
|
||||||
|
targetPOI = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetPOI(Dictionary<String, PointOfInterest> poiTokens){
|
||||||
|
|
||||||
|
if (POIToken != null && POIToken.length() > 0){
|
||||||
|
PointOfInterest tokenTarget = poiTokens.get(POIToken);
|
||||||
|
if (tokenTarget != null){
|
||||||
|
setTargetPOI(tokenTarget);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
System.out.println("Quest Stage '" + this.name+ "' failed to generate POI from token reference: '" + POIToken +"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (here){
|
||||||
|
setTargetPOI(AdventureQuestController.instance().mostRecentPOI);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!anyPOI) {
|
||||||
|
List<PointOfInterest> candidates = Current.world().getAllPointOfInterest();
|
||||||
|
for (String tag : POITags)
|
||||||
|
{
|
||||||
|
candidates.removeIf(q -> Arrays.stream(q.getData().questTags).noneMatch(tag::equals));
|
||||||
|
}
|
||||||
|
if (candidates.size() < 1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
count1 = (count1* candidates.size()/ 100);
|
||||||
|
count2 = (count2* candidates.size()) /100;
|
||||||
|
int targetIndex = Math.max(0,(int) (count1 - count2 + (new Random().nextFloat() * count2 * 2)));
|
||||||
|
|
||||||
|
if (targetIndex < candidates.size() && targetIndex > 0 && count1 > 0) {
|
||||||
|
candidates.sort(new AdventureQuestController.DistanceSort());
|
||||||
|
setTargetPOI(candidates.get(targetIndex));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (count1 !=0 || count2 != 0) {
|
||||||
|
System.out.println("Quest Stage '" + this.name + "' has invalid count1 ('" + count1 + "') and/or count2 ('" + count2 + "') value");
|
||||||
|
}
|
||||||
|
setTargetPOI(Aggregates.random(candidates));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//"else" any POI matching all the POITags is valid, evaluate as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnemySprite getTargetSprite() {
|
||||||
|
return targetSprite;
|
||||||
|
}
|
||||||
|
public void setTargetEnemyData(EnemyData target) {
|
||||||
|
targetEnemyData = target;
|
||||||
|
}
|
||||||
|
public EnemyData getTargetEnemyData() {
|
||||||
|
if (targetEnemyData == null & targetSprite!=null)
|
||||||
|
return targetSprite.getData();
|
||||||
|
return targetEnemyData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetSprite(EnemySprite target) {
|
||||||
|
targetSprite = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus updateEnterPOI(PointOfInterest entered) {
|
||||||
|
if (getStatus() == AdventureQuestController.QuestStatus.Complete){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else if (getStatus() == AdventureQuestController.QuestStatus.Failed){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
checkIfInTargetLocation(entered);
|
||||||
|
if (inTargetLocation &&
|
||||||
|
(this.objective == AdventureQuestController.ObjectiveTypes.Delivery ||
|
||||||
|
this.objective == AdventureQuestController.ObjectiveTypes.Travel)) {
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus updateMapFlag(String mapFlag, int mapFlagValue){
|
||||||
|
if (getStatus() == AdventureQuestController.QuestStatus.Complete){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else if (getStatus() == AdventureQuestController.QuestStatus.Failed){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.objective == AdventureQuestController.ObjectiveTypes.MapFlag) {
|
||||||
|
if (mapFlag.equals(this.mapFlag) && mapFlagValue >= this.mapFlagValue)
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public AdventureQuestController.QuestStatus updateLeave(){
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Complete){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Failed){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
inTargetLocation = false; //todo: handle case when called between multi-map PoIs (if necessary)
|
||||||
|
if (this.objective == AdventureQuestController.ObjectiveTypes.Leave){
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus updateWin(EnemySprite defeated, boolean mapCleared){
|
||||||
|
//todo - Does this need to also be called for alternate mob removal types?
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Complete){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Failed){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
if (this.objective == AdventureQuestController.ObjectiveTypes.Clear)
|
||||||
|
{
|
||||||
|
if (mapCleared && inTargetLocation)
|
||||||
|
{
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.objective == AdventureQuestController.ObjectiveTypes.Defeat) {
|
||||||
|
{
|
||||||
|
List<String> defeatedTags = Arrays.stream(defeated.getData().questTags).collect(Collectors.toList());
|
||||||
|
for (String targetTag : enemyTags) {
|
||||||
|
if (!defeatedTags.contains(targetTag)) {
|
||||||
|
//Does not count toward objective
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//All tags matched, kill confirmed
|
||||||
|
if (++progress1 >= count1){
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this.objective == AdventureQuestController.ObjectiveTypes.Hunt)
|
||||||
|
{
|
||||||
|
if (defeated.equals(targetSprite)){
|
||||||
|
status = AdventureQuestController.QuestStatus.Complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkIfInTargetLocation(PointOfInterest entered){
|
||||||
|
if (targetPOI == null){
|
||||||
|
List<String> enteredTags = Arrays.stream(entered.getData().questTags).collect(Collectors.toList());
|
||||||
|
for (String tag : POITags){
|
||||||
|
if (!enteredTags.contains(tag)) {
|
||||||
|
inTargetLocation = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!targetPOI.equals(entered)){
|
||||||
|
inTargetLocation = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inTargetLocation = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus updateLose(EnemySprite defeatedBy){
|
||||||
|
|
||||||
|
if (status != AdventureQuestController.QuestStatus.Failed && this.objective == AdventureQuestController.ObjectiveTypes.Defeat) {
|
||||||
|
{
|
||||||
|
List<String> defeatedByTags = Arrays.stream(defeatedBy.getData().questTags).collect(Collectors.toList());
|
||||||
|
for (String targetTag : enemyTags) {
|
||||||
|
if (!defeatedByTags.contains(targetTag)) {
|
||||||
|
//Does not count
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//All tags matched
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Active && ++progress2 >= count2){
|
||||||
|
status = AdventureQuestController.QuestStatus.Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (status == AdventureQuestController.QuestStatus.Active && this.objective == AdventureQuestController.ObjectiveTypes.Hunt)
|
||||||
|
{
|
||||||
|
if (defeatedBy.equals(targetSprite)){
|
||||||
|
status = AdventureQuestController.QuestStatus.Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController.QuestStatus updateDespawn(EnemySprite despawned){
|
||||||
|
if (status == AdventureQuestController.QuestStatus.Active && this.objective == AdventureQuestController.ObjectiveTypes.Hunt)
|
||||||
|
{
|
||||||
|
if (despawned.equals(targetSprite)){
|
||||||
|
status = AdventureQuestController.QuestStatus.Failed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestStage(){}
|
||||||
|
public AdventureQuestStage(AdventureQuestStage other){
|
||||||
|
this.status = other.status;
|
||||||
|
this.prologueDisplayed = other.prologueDisplayed;
|
||||||
|
this.prologue = new DialogData(other.prologue);
|
||||||
|
this.epilogueDisplayed = other.epilogueDisplayed;
|
||||||
|
this.epilogue = new DialogData(other.epilogue);
|
||||||
|
this.failureDialog = new DialogData(other.failureDialog);
|
||||||
|
this.name = other.name;
|
||||||
|
this.description = other.description;
|
||||||
|
this.progress1 = other.progress1;
|
||||||
|
this.progress2 = other.progress2;
|
||||||
|
this.progress3 = other.progress3;
|
||||||
|
this.count1 = other.count1;
|
||||||
|
this.count2 = other.count2;
|
||||||
|
this.count3 = other.count3;
|
||||||
|
this.enemyTags = other.enemyTags;
|
||||||
|
this.anyPOI = other.anyPOI;
|
||||||
|
this.here = other.here;
|
||||||
|
this.targetPOI = other.targetPOI;
|
||||||
|
this.objective = other.objective;
|
||||||
|
this.mapFlagValue = other.mapFlagValue;
|
||||||
|
this.mapFlag = other.mapFlag;
|
||||||
|
this.equipNames = other.equipNames;
|
||||||
|
this.mixedEnemies = other.mixedEnemies;
|
||||||
|
this.itemNames = other.itemNames;
|
||||||
|
this.prequisitesComplete = other.prequisitesComplete;
|
||||||
|
this.prerequisiteNames = other.prerequisiteNames;
|
||||||
|
this.POIToken = other.POIToken;
|
||||||
|
this.id = other.id;
|
||||||
|
this.POITags = other.POITags;
|
||||||
|
this.targetEnemyData = other.targetEnemyData;
|
||||||
|
this.deliveryItem = other.deliveryItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,23 +1,50 @@
|
|||||||
package forge.adventure.data;
|
package forge.adventure.data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog Data JSON loader class.
|
* Dialog Data JSON loader class.
|
||||||
* Carries all text, branches and effects of dialogs.
|
* Carries all text, branches and effects of dialogs.
|
||||||
*/
|
*/
|
||||||
public class DialogData {
|
public class DialogData implements Serializable {
|
||||||
public ActionData[] action; //List of effects to cause when the dialog shows.
|
public ActionData[] action = new ActionData[0]; //List of effects to cause when the dialog shows.
|
||||||
public ConditionData[] condition; //List of conditions for the action to show.
|
public ConditionData[] condition = new ConditionData[0]; //List of conditions for the action to show.
|
||||||
public String name; //Text to display when action is listed as a button.
|
public String name = ""; //Text to display when action is listed as a button.
|
||||||
public String locname; //References a localized string for the button labels.
|
public String locname = ""; //References a localized string for the button labels.
|
||||||
public String text; //The text body.
|
public String text = ""; //The text body.
|
||||||
public String loctext; //References a localized string for the text body.
|
public String loctext= ""; //References a localized string for the text body.
|
||||||
public DialogData[] options; //List of sub-dialogs. Show up as options in the current one.
|
public DialogData[] options = new DialogData[0]; //List of sub-dialogs. Show up as options in the current one.
|
||||||
|
|
||||||
|
public DialogData(){}
|
||||||
|
public DialogData(DialogData other){
|
||||||
|
if (other == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.action = other.action.clone();
|
||||||
|
this.condition = other.condition.clone();
|
||||||
|
this.name = other.name;
|
||||||
|
this.locname = other.locname.isEmpty()?"":("Copy of " + other.locname);
|
||||||
|
this.text = other.text;
|
||||||
|
this.loctext = other.loctext;
|
||||||
|
List<DialogData> clonedOptions = new ArrayList<>();
|
||||||
|
for (DialogData option: other.options){
|
||||||
|
clonedOptions.add(new DialogData(option));
|
||||||
|
}
|
||||||
|
this.options = clonedOptions.toArray(new DialogData[0]);
|
||||||
|
this.voiceFile = other.voiceFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
public String voiceFile;
|
public String voiceFile;
|
||||||
|
|
||||||
static public class ActionData {
|
static public class ActionData implements Serializable {
|
||||||
static public class QuestFlag {
|
static public class QuestFlag implements Serializable{
|
||||||
public String key;
|
public String key;
|
||||||
public int val;
|
public int val;
|
||||||
}
|
}
|
||||||
@@ -25,6 +52,7 @@ public class DialogData {
|
|||||||
public String addItem; //Add item name to inventory.
|
public String addItem; //Add item name to inventory.
|
||||||
public int addLife = 0; //Gives the player X health. Negative to take.
|
public int addLife = 0; //Gives the player X health. Negative to take.
|
||||||
public int addGold = 0; //Gives the player X gold. Negative to take.
|
public int addGold = 0; //Gives the player X gold. Negative to take.
|
||||||
|
|
||||||
public int deleteMapObject = 0; //Remove ID from the map. -1 for self.
|
public int deleteMapObject = 0; //Remove ID from the map. -1 for self.
|
||||||
public int battleWithActorID = 0; //Start a battle with enemy ID. -1 for self if possible.
|
public int battleWithActorID = 0; //Start a battle with enemy ID. -1 for self if possible.
|
||||||
public EffectData giveBlessing; //Give a blessing to the player.
|
public EffectData giveBlessing; //Give a blessing to the player.
|
||||||
@@ -35,6 +63,41 @@ public class DialogData {
|
|||||||
public QuestFlag setQuestFlag; //Set quest flag.
|
public QuestFlag setQuestFlag; //Set quest flag.
|
||||||
public QuestFlag setMapFlag; //Set map flag.
|
public QuestFlag setMapFlag; //Set map flag.
|
||||||
|
|
||||||
|
public RewardData[] grantRewards = new RewardData[0]; //launch a RewardScene with the provided data.
|
||||||
|
public String issueQuest; //Add quest with this ID to the player's questlog.
|
||||||
|
|
||||||
|
public int addMapReputation = 0; //Gives the player X reputation points in this POI. Negative to take.
|
||||||
|
public String POIReference; //used with addMapReputation when a quest step affects reputation in another location
|
||||||
|
|
||||||
|
public ActionData(){}
|
||||||
|
|
||||||
|
public ActionData(ActionData other){
|
||||||
|
removeItem = other.removeItem;
|
||||||
|
addItem = other.removeItem;
|
||||||
|
addLife = other.addLife;
|
||||||
|
addGold = other.addGold;
|
||||||
|
deleteMapObject = other.deleteMapObject;
|
||||||
|
battleWithActorID = other.battleWithActorID;
|
||||||
|
giveBlessing = other.giveBlessing;
|
||||||
|
setColorIdentity = other.setColorIdentity;
|
||||||
|
advanceQuestFlag = other.advanceQuestFlag;
|
||||||
|
advanceMapFlag = other.advanceMapFlag;
|
||||||
|
setEffect = other.setEffect;
|
||||||
|
setQuestFlag = new QuestFlag();
|
||||||
|
if (other.setQuestFlag != null) {
|
||||||
|
setQuestFlag.key = other.setQuestFlag.key;
|
||||||
|
setQuestFlag.val = other.setQuestFlag.val;
|
||||||
|
}
|
||||||
|
setMapFlag = new QuestFlag();
|
||||||
|
if (other.setMapFlag != null) {
|
||||||
|
setMapFlag.key = other.setMapFlag.key;
|
||||||
|
setMapFlag.val = other.setMapFlag.val;
|
||||||
|
}
|
||||||
|
grantRewards = other.grantRewards.clone();
|
||||||
|
issueQuest = other.issueQuest;
|
||||||
|
addMapReputation = other.addMapReputation;
|
||||||
|
POIReference = other.POIReference;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public class ConditionData {
|
static public class ConditionData {
|
||||||
@@ -47,6 +110,7 @@ public class DialogData {
|
|||||||
public int actorID = 0; //Check for an actor ID.
|
public int actorID = 0; //Check for an actor ID.
|
||||||
public String hasBlessing = null; //Check for specific blessing, if named.
|
public String hasBlessing = null; //Check for specific blessing, if named.
|
||||||
public int hasGold = 0; //Check for player gold. True if gold is equal or higher than X.
|
public int hasGold = 0; //Check for player gold. True if gold is equal or higher than X.
|
||||||
|
public int hasMapReputation = Integer.MIN_VALUE; //Check for player reputation in this POI. True if reputation is equal or higher than X.
|
||||||
public int hasLife = 0; //Check for player life. True if life is equal or higher than X.
|
public int hasLife = 0; //Check for player life. True if life is equal or higher than X.
|
||||||
public String colorIdentity = null; //Check for player's current color identity.
|
public String colorIdentity = null; //Check for player's current color identity.
|
||||||
public String checkQuestFlag = null; //Check if a quest flag is not 0. False if equals 0 (not started, not set).
|
public String checkQuestFlag = null; //Check if a quest flag is not 0. False if equals 0 (not started, not set).
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import forge.adventure.util.*;
|
|||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data class that will be used to read Json configuration files
|
* Data class that will be used to read Json configuration files
|
||||||
* BiomeData
|
* BiomeData
|
||||||
* contains the information of enemies
|
* contains the information of enemies
|
||||||
*/
|
*/
|
||||||
public class EnemyData {
|
public class EnemyData implements Serializable {
|
||||||
public String name;
|
public String name;
|
||||||
public String nameOverride;
|
public String nameOverride;
|
||||||
public String sprite;
|
public String sprite;
|
||||||
@@ -31,6 +33,9 @@ public class EnemyData {
|
|||||||
public EnemyData nextEnemy;
|
public EnemyData nextEnemy;
|
||||||
public int teamNumber = -1;
|
public int teamNumber = -1;
|
||||||
|
|
||||||
|
public String[] questTags = new String[0];
|
||||||
|
public float lifetime;
|
||||||
|
|
||||||
public EnemyData() {
|
public EnemyData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +58,8 @@ public class EnemyData {
|
|||||||
teamNumber = enemyData.teamNumber;
|
teamNumber = enemyData.teamNumber;
|
||||||
nextEnemy = enemyData.nextEnemy == null ? null : new EnemyData(enemyData.nextEnemy);
|
nextEnemy = enemyData.nextEnemy == null ? null : new EnemyData(enemyData.nextEnemy);
|
||||||
nameOverride = enemyData.nameOverride == null ? "" : enemyData.nameOverride;
|
nameOverride = enemyData.nameOverride == null ? "" : enemyData.nameOverride;
|
||||||
|
questTags = enemyData.questTags.clone();
|
||||||
|
lifetime = enemyData.lifetime;
|
||||||
if (enemyData.scale == 0.0f) {
|
if (enemyData.scale == 0.0f) {
|
||||||
scale = 1.0f;
|
scale = 1.0f;
|
||||||
}
|
}
|
||||||
@@ -71,4 +78,11 @@ public class EnemyData {
|
|||||||
}
|
}
|
||||||
return CardUtil.getDeck(deck[Current.player().getEnemyDeckNumber(this.name, deck.length)], true, isFantasyMode, colors, life > 13, life > 16 && useGeneticAI);
|
return CardUtil.getDeck(deck[Current.player().getEnemyDeckNumber(this.name, deck.length)], true, isFantasyMode, colors, life > 13, life > 16 && useGeneticAI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName(){
|
||||||
|
//todo: make this the default accessor for anything seen in UI
|
||||||
|
if (!nameOverride.isEmpty())
|
||||||
|
return nameOverride;
|
||||||
|
return name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ import com.badlogic.gdx.utils.Json;
|
|||||||
import forge.adventure.util.Config;
|
import forge.adventure.util.Config;
|
||||||
import forge.adventure.util.Paths;
|
import forge.adventure.util.Paths;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data class that will be used to read Json configuration files
|
* Data class that will be used to read Json configuration files
|
||||||
* BiomeData
|
* BiomeData
|
||||||
* contains the information for the point of interests like towns and dungeons
|
* contains the information for the point of interests like towns and dungeons
|
||||||
*/
|
*/
|
||||||
public class PointOfInterestData {
|
public class PointOfInterestData implements Serializable {
|
||||||
public String name;
|
public String name;
|
||||||
public String type;
|
public String type;
|
||||||
public int count;
|
public int count;
|
||||||
@@ -21,6 +23,8 @@ public class PointOfInterestData {
|
|||||||
public float radiusFactor;
|
public float radiusFactor;
|
||||||
public float offsetX=0f;
|
public float offsetX=0f;
|
||||||
public float offsetY=0f;
|
public float offsetY=0f;
|
||||||
|
public boolean active = true;
|
||||||
|
public String[] questTags = new String[0];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -31,9 +35,7 @@ public class PointOfInterestData {
|
|||||||
Json json = new Json();
|
Json json = new Json();
|
||||||
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
|
FileHandle handle = Config.instance().getFile(Paths.POINTS_OF_INTEREST);
|
||||||
if (handle.exists()) {
|
if (handle.exists()) {
|
||||||
Array readJson = json.fromJson(Array.class, PointOfInterestData.class, handle);
|
pointOfInterestList = json.fromJson(Array.class, PointOfInterestData.class, handle);
|
||||||
pointOfInterestList = readJson;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -60,5 +62,7 @@ public class PointOfInterestData {
|
|||||||
radiusFactor=other.radiusFactor;
|
radiusFactor=other.radiusFactor;
|
||||||
offsetX=other.offsetX;
|
offsetX=other.offsetX;
|
||||||
offsetY=other.offsetY;
|
offsetY=other.offsetY;
|
||||||
|
active=other.active;
|
||||||
|
questTags = other.questTags.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,8 @@ import forge.adventure.world.WorldSave;
|
|||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.Serializable;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data class that will be used to read Json configuration files
|
* Data class that will be used to read Json configuration files
|
||||||
@@ -24,7 +22,7 @@ import java.util.List;
|
|||||||
* that can be a random card, gold or items.
|
* that can be a random card, gold or items.
|
||||||
* Also used for deck generation and shops
|
* Also used for deck generation and shops
|
||||||
*/
|
*/
|
||||||
public class RewardData {
|
public class RewardData implements Serializable {
|
||||||
public String type;
|
public String type;
|
||||||
public float probability;
|
public float probability;
|
||||||
public int count;
|
public int count;
|
||||||
@@ -51,6 +49,9 @@ public class RewardData {
|
|||||||
public RewardData() { }
|
public RewardData() { }
|
||||||
|
|
||||||
public RewardData(RewardData rewardData) {
|
public RewardData(RewardData rewardData) {
|
||||||
|
if (rewardData == null)
|
||||||
|
return;
|
||||||
|
|
||||||
type =rewardData.type;
|
type =rewardData.type;
|
||||||
probability =rewardData.probability;
|
probability =rewardData.probability;
|
||||||
count =rewardData.count;
|
count =rewardData.count;
|
||||||
@@ -115,17 +116,24 @@ public class RewardData {
|
|||||||
return allCards;
|
return allCards;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Array<Reward> generate(boolean isForEnemy) {
|
public Array<Reward> generate(boolean isForEnemy, boolean useSeedlessRandom) {
|
||||||
return generate(isForEnemy, null);
|
return generate(isForEnemy, null, useSeedlessRandom);
|
||||||
}
|
}
|
||||||
public Array<Reward> generate(boolean isForEnemy, Iterable<PaperCard> cards) {
|
|
||||||
|
public Array<Reward> generate(boolean isForEnemy, Iterable<PaperCard> cards, boolean useSeedlessRandom) {
|
||||||
|
|
||||||
|
Random rewardRandom = useSeedlessRandom?new Random():WorldSave.getCurrentSave().getWorld().getRandom();
|
||||||
|
//Keep using same generation method for shop rewards, but fully randomize loot drops by not using the instance pre-seeded by the map
|
||||||
|
|
||||||
if(allCards==null) initializeAllCards();
|
if(allCards==null) initializeAllCards();
|
||||||
Array<Reward> ret=new Array<>();
|
Array<Reward> ret=new Array<>();
|
||||||
if(probability == 0 || WorldSave.getCurrentSave().getWorld().getRandom().nextFloat() <= probability) {
|
|
||||||
|
|
||||||
|
if(probability == 0 || rewardRandom.nextFloat() <= probability) {
|
||||||
if(type==null || type.isEmpty())
|
if(type==null || type.isEmpty())
|
||||||
type="randomCard";
|
type="randomCard";
|
||||||
int maxCount=Math.round(addMaxCount*Current.player().getDifficulty().rewardMaxFactor);
|
int maxCount=Math.round(addMaxCount*Current.player().getDifficulty().rewardMaxFactor);
|
||||||
int addedCount = (maxCount > 0 ? WorldSave.getCurrentSave().getWorld().getRandom().nextInt(maxCount) : 0);
|
int addedCount = (maxCount > 0 ? rewardRandom.nextInt(maxCount) : 0);
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case "Union":
|
case "Union":
|
||||||
@@ -137,7 +145,7 @@ public class RewardData {
|
|||||||
|
|
||||||
if (finalPool.size() > 0){
|
if (finalPool.size() > 0){
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
ret.add(new Reward(finalPool.get(WorldSave.getCurrentSave().getWorld().getRandom().nextInt(finalPool.size()))));
|
ret.add(new Reward(finalPool.get(rewardRandom.nextInt(finalPool.size()))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -148,7 +156,7 @@ public class RewardData {
|
|||||||
ret.add(new Reward(StaticData.instance().getCommonCards().getCard(cardName)));
|
ret.add(new Reward(StaticData.instance().getCommonCards().getCard(cardName)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(PaperCard card:CardUtil.generateCards(isForEnemy ? allEnemyCards:allCards,this, count+addedCount)) {
|
for(PaperCard card:CardUtil.generateCards(isForEnemy ? allEnemyCards:allCards,this, count+addedCount, rewardRandom)) {
|
||||||
ret.add(new Reward(card));
|
ret.add(new Reward(card));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -168,7 +176,7 @@ public class RewardData {
|
|||||||
break;
|
break;
|
||||||
case "deckCard":
|
case "deckCard":
|
||||||
if(cards == null) return ret;
|
if(cards == null) return ret;
|
||||||
for(PaperCard card: CardUtil.generateCards(cards,this, count + addedCount + Current.player().bonusDeckCards() )) {
|
for(PaperCard card: CardUtil.generateCards(cards,this, count + addedCount + Current.player().bonusDeckCards() ,rewardRandom)) {
|
||||||
ret.add(new Reward(card));
|
ret.add(new Reward(card));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -193,7 +201,7 @@ public class RewardData {
|
|||||||
static public Iterable<Reward> generateAll(Iterable<RewardData> dataList, boolean isForEnemy) {
|
static public Iterable<Reward> generateAll(Iterable<RewardData> dataList, boolean isForEnemy) {
|
||||||
Array<Reward> ret=new Array<Reward>();
|
Array<Reward> ret=new Array<Reward>();
|
||||||
for (RewardData data:dataList)
|
for (RewardData data:dataList)
|
||||||
ret.addAll(data.generate(isForEnemy));
|
ret.addAll(data.generate(isForEnemy, false));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static public List<PaperCard> rewardsToCards(Iterable<Reward> dataList) {
|
static public List<PaperCard> rewardsToCards(Iterable<Reward> dataList) {
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Null;
|
import com.badlogic.gdx.utils.Null;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import forge.adventure.data.DifficultyData;
|
import forge.adventure.data.*;
|
||||||
import forge.adventure.data.EffectData;
|
|
||||||
import forge.adventure.data.HeroListData;
|
|
||||||
import forge.adventure.data.ItemData;
|
|
||||||
import forge.adventure.util.*;
|
import forge.adventure.util.*;
|
||||||
import forge.adventure.world.WorldSave;
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
@@ -23,10 +20,7 @@ import forge.sound.SoundSystem;
|
|||||||
import forge.util.ItemPool;
|
import forge.util.ItemPool;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that represents the player (not the player sprite)
|
* Class that represents the player (not the player sprite)
|
||||||
@@ -59,6 +53,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
|
|
||||||
private final Array<String> inventoryItems=new Array<>();
|
private final Array<String> inventoryItems=new Array<>();
|
||||||
private final HashMap<String,String> equippedItems=new HashMap<>();
|
private final HashMap<String,String> equippedItems=new HashMap<>();
|
||||||
|
private List<AdventureQuestData> quests= new ArrayList<>();
|
||||||
|
|
||||||
// Fantasy/Chaos mode settings.
|
// Fantasy/Chaos mode settings.
|
||||||
private boolean fantasyMode = false;
|
private boolean fantasyMode = false;
|
||||||
@@ -99,6 +94,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
inventoryItems.clear();
|
inventoryItems.clear();
|
||||||
equippedItems.clear();
|
equippedItems.clear();
|
||||||
questFlags.clear();
|
questFlags.clear();
|
||||||
|
quests.clear();
|
||||||
cards.clear();
|
cards.clear();
|
||||||
statistic.clear();
|
statistic.clear();
|
||||||
newCards.clear();
|
newCards.clear();
|
||||||
@@ -292,6 +288,12 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
questFlags.put(keys[i], values[i]);
|
questFlags.put(keys[i], values[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(data.containsKey("quests")){
|
||||||
|
quests.clear();
|
||||||
|
Object[] q = (Object[]) data.readObject("quests");
|
||||||
|
for (Object itsReallyAQuest: q)
|
||||||
|
quests.add((AdventureQuestData) itsReallyAQuest);
|
||||||
|
}
|
||||||
|
|
||||||
for(int i=0;i<NUMBER_OF_DECKS;i++) {
|
for(int i=0;i<NUMBER_OF_DECKS;i++) {
|
||||||
if(!data.containsKey("deck_name_" + i)) {
|
if(!data.containsKey("deck_name_" + i)) {
|
||||||
@@ -372,6 +374,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
data.storeObject("questFlagsKey", questFlagsKey.toArray(new String[0]));
|
data.storeObject("questFlagsKey", questFlagsKey.toArray(new String[0]));
|
||||||
data.storeObject("questFlagsValue", questFlagsValue.toArray(new Byte[0]));
|
data.storeObject("questFlagsValue", questFlagsValue.toArray(new Byte[0]));
|
||||||
|
data.storeObject("quests", quests.toArray());
|
||||||
|
|
||||||
data.storeObject("deckCards",deck.getMain().toCardList("\n").split("\n"));
|
data.storeObject("deckCards",deck.getMain().toCardList("\n").split("\n"));
|
||||||
if(deck.get(DeckSection.Sideboard)!=null)
|
if(deck.get(DeckSection.Sideboard)!=null)
|
||||||
@@ -702,6 +705,37 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
questFlags.clear();
|
questFlags.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addQuest(String questID){
|
||||||
|
int id = Integer.parseInt(questID);
|
||||||
|
addQuest(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addQuest(int questID){
|
||||||
|
AdventureQuestData toAdd = AdventureQuestController.instance().generateQuest(questID);
|
||||||
|
|
||||||
|
if (toAdd != null){
|
||||||
|
addQuest(toAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addQuest(AdventureQuestData q){
|
||||||
|
//TODO: add a config flag for this
|
||||||
|
boolean autoTrack = true;
|
||||||
|
for (AdventureQuestData existing : quests){
|
||||||
|
if (autoTrack && existing.isTracked)
|
||||||
|
{
|
||||||
|
autoTrack = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
q.isTracked = autoTrack;
|
||||||
|
quests.add(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AdventureQuestData> getQuests() {
|
||||||
|
return quests;
|
||||||
|
}
|
||||||
|
|
||||||
public int getEnemyDeckNumber(String enemyName, int maxDecks){
|
public int getEnemyDeckNumber(String enemyName, int maxDecks){
|
||||||
int deckNumber = 0;
|
int deckNumber = 0;
|
||||||
if (statistic.getWinLossRecord().get(enemyName)!=null)
|
if (statistic.getWinLossRecord().get(enemyName)!=null)
|
||||||
@@ -721,4 +755,7 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
|||||||
return deckNumber;
|
return deckNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeQuest(AdventureQuestData quest) {
|
||||||
|
quests.remove(quest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import forge.adventure.util.Config;
|
|||||||
import forge.adventure.util.SaveFileContent;
|
import forge.adventure.util.SaveFileContent;
|
||||||
import forge.adventure.util.SaveFileData;
|
import forge.adventure.util.SaveFileData;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Point of interest stored in the world
|
* Point of interest stored in the world
|
||||||
*/
|
*/
|
||||||
public class PointOfInterest implements SaveFileContent {
|
public class PointOfInterest implements Serializable, SaveFileContent {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(SaveFileData saveFileData) {
|
public void load(SaveFileData saveFileData) {
|
||||||
@@ -24,7 +24,13 @@ public class PointOfInterest implements SaveFileContent {
|
|||||||
data=PointOfInterestData.getPointOfInterest(saveFileData.readString("name"));
|
data=PointOfInterestData.getPointOfInterest(saveFileData.readString("name"));
|
||||||
rectangle.set(saveFileData.readRectangle("rectangle"));
|
rectangle.set(saveFileData.readRectangle("rectangle"));
|
||||||
spriteIndex=saveFileData.readInt("spriteIndex");
|
spriteIndex=saveFileData.readInt("spriteIndex");
|
||||||
|
if (saveFileData.containsKey("active")){
|
||||||
|
active = saveFileData.readBool("active");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
active = data.active;
|
||||||
|
}
|
||||||
|
|
||||||
oldMapId="";
|
oldMapId="";
|
||||||
Array<Sprite> textureAtlas = Config.instance().getAtlas(this.data.spriteAtlas).createSprites(this.data.sprite);
|
Array<Sprite> textureAtlas = Config.instance().getAtlas(this.data.spriteAtlas).createSprites(this.data.sprite);
|
||||||
@@ -39,15 +45,17 @@ public class PointOfInterest implements SaveFileContent {
|
|||||||
data.store("position",position);
|
data.store("position",position);
|
||||||
data.store("rectangle",rectangle);
|
data.store("rectangle",rectangle);
|
||||||
data.store("spriteIndex",spriteIndex);
|
data.store("spriteIndex",spriteIndex);
|
||||||
|
data.store("active",active);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointOfInterestData data;
|
PointOfInterestData data;
|
||||||
final Vector2 position=new Vector2();
|
final Vector2 position=new Vector2();
|
||||||
Sprite sprite;
|
transient Sprite sprite;
|
||||||
int spriteIndex;
|
int spriteIndex;
|
||||||
final Rectangle rectangle=new Rectangle();
|
final Rectangle rectangle=new Rectangle();
|
||||||
String oldMapId="";
|
String oldMapId="";
|
||||||
|
boolean active = true;
|
||||||
public PointOfInterest() {
|
public PointOfInterest() {
|
||||||
}
|
}
|
||||||
public PointOfInterest(PointOfInterestData d, Vector2 pos, Random rand) {
|
public PointOfInterest(PointOfInterestData d, Vector2 pos, Random rand) {
|
||||||
@@ -58,6 +66,7 @@ public class PointOfInterest implements SaveFileContent {
|
|||||||
spriteIndex = rand.nextInt(Integer.SIZE - 1) % textureAtlas.size;
|
spriteIndex = rand.nextInt(Integer.SIZE - 1) % textureAtlas.size;
|
||||||
sprite = textureAtlas.get(spriteIndex);
|
sprite = textureAtlas.get(spriteIndex);
|
||||||
data = d;
|
data = d;
|
||||||
|
active = d.active;
|
||||||
position.set(pos);
|
position.set(pos);
|
||||||
|
|
||||||
rectangle.set(position.x, position.y, sprite.getWidth(), sprite.getHeight());
|
rectangle.set(position.x, position.y, sprite.getWidth(), sprite.getHeight());
|
||||||
@@ -66,6 +75,7 @@ public class PointOfInterest implements SaveFileContent {
|
|||||||
spriteIndex = parent.spriteIndex;
|
spriteIndex = parent.spriteIndex;
|
||||||
sprite = parent.sprite;
|
sprite = parent.sprite;
|
||||||
data = d;
|
data = d;
|
||||||
|
active = d.active;
|
||||||
position.set(parent.position);
|
position.set(parent.position);
|
||||||
oldMapId=parent.getID();
|
oldMapId=parent.getID();
|
||||||
rectangle.set(position.x, position.y, sprite.getWidth(), sprite.getHeight());
|
rectangle.set(position.x, position.y, sprite.getWidth(), sprite.getHeight());
|
||||||
@@ -98,4 +108,14 @@ public class PointOfInterest implements SaveFileContent {
|
|||||||
return getSeedOffset()+data.name+"/"+oldMapId;
|
return getSeedOffset()+data.name+"/"+oldMapId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getActive() {return active;}
|
||||||
|
|
||||||
|
public void setActive(boolean active) {this.active = active;}
|
||||||
|
|
||||||
|
public Vector2 getNavigationVector(Vector2 origin){
|
||||||
|
Vector2 navVector = new Vector2(rectangle.x + rectangle.getWidth() / 2, rectangle.y + rectangle.getHeight() / 2);
|
||||||
|
if (origin != null) navVector.sub(origin);
|
||||||
|
|
||||||
|
return navVector;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public class PointOfInterestChanges implements SaveFileContent {
|
|||||||
private final java.util.Map<String, Byte> mapFlags = new HashMap<>();
|
private final java.util.Map<String, Byte> mapFlags = new HashMap<>();
|
||||||
private final java.util.Map<Integer, Long> shopSeeds = new HashMap<>();
|
private final java.util.Map<Integer, Long> shopSeeds = new HashMap<>();
|
||||||
private final java.util.Map<Integer, Float> shopModifiers = new HashMap<>();
|
private final java.util.Map<Integer, Float> shopModifiers = new HashMap<>();
|
||||||
|
private final java.util.Map<Integer, Integer> reputation = new HashMap<>();
|
||||||
|
|
||||||
public static class Map extends HashMap<String,PointOfInterestChanges> implements SaveFileContent {
|
public static class Map extends HashMap<String,PointOfInterestChanges> implements SaveFileContent {
|
||||||
@Override
|
@Override
|
||||||
@@ -103,6 +104,7 @@ public class PointOfInterestChanges implements SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateNewShopSeed(int objectID){
|
public void generateNewShopSeed(int objectID){
|
||||||
|
|
||||||
shopSeeds.put(objectID, Current.world().getRandom().nextLong());
|
shopSeeds.put(objectID, Current.world().getRandom().nextLong());
|
||||||
cardsBought.put(objectID, new HashSet<>()); //Allows cards to appear in slots of previous purchases
|
cardsBought.put(objectID, new HashSet<>()); //Allows cards to appear in slots of previous purchases
|
||||||
}
|
}
|
||||||
@@ -134,11 +136,33 @@ public class PointOfInterestChanges implements SaveFileContent {
|
|||||||
return shopModifiers.get(0);
|
return shopModifiers.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTownModifier(float mod){
|
public void addMapReputation(int delta)
|
||||||
shopModifiers.put(0, mod);
|
{
|
||||||
|
addObjectReputation(0, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addObjectReputation(int id, int delta)
|
||||||
|
{
|
||||||
|
reputation.put(id, (reputation.containsKey(id)?reputation.get(id):0) + delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMapReputation(){
|
||||||
|
return getObjectReputation(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getObjectReputation(int id){
|
||||||
|
if (!reputation.containsKey(id))
|
||||||
|
{
|
||||||
|
reputation.put(id, 0);
|
||||||
|
}
|
||||||
|
return reputation.get(id);
|
||||||
}
|
}
|
||||||
public boolean hasDeletedObjects() {
|
public boolean hasDeletedObjects() {
|
||||||
return deletedObjects != null && !deletedObjects.isEmpty();
|
return deletedObjects != null && !deletedObjects.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearDeletedObjects() {
|
||||||
|
// reset map when assigning as a quest target that needs enemies
|
||||||
|
deletedObjects.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class PointOfInterestMap implements SaveFileContent {
|
|||||||
mapObjects = new List[numberOfChunksX][numberOfChunksY];
|
mapObjects = new List[numberOfChunksX][numberOfChunksY];
|
||||||
for (int x = 0; x < numberOfChunksX; x++) {
|
for (int x = 0; x < numberOfChunksX; x++) {
|
||||||
for (int y = 0; y < numberOfChunksY; y++) {
|
for (int y = 0; y < numberOfChunksY; y++) {
|
||||||
mapObjects[x][y] = new ArrayList();
|
mapObjects[x][y] = new ArrayList<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,9 +53,23 @@ public class PointOfInterestMap implements SaveFileContent {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PointOfInterest> getAllPointOfInterest() {
|
||||||
|
List<PointOfInterest> allPOI = new ArrayList<>();
|
||||||
|
|
||||||
|
for(List<PointOfInterest>[] poiList1:mapObjects)
|
||||||
|
{
|
||||||
|
for(List<PointOfInterest> poiList:poiList1)
|
||||||
|
{
|
||||||
|
allPOI.addAll(poiList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allPOI;
|
||||||
|
}
|
||||||
|
|
||||||
public List<PointOfInterest> pointsOfInterest(int chunkX, int chunkY) {
|
public List<PointOfInterest> pointsOfInterest(int chunkX, int chunkY) {
|
||||||
if (chunkX >= numberOfChunksX || chunkY >= numberOfChunksY || chunkX < 0 || chunkY < 0)
|
if (chunkX >= numberOfChunksX || chunkY >= numberOfChunksY || chunkX < 0 || chunkY < 0)
|
||||||
return new ArrayList<PointOfInterest>();
|
return new ArrayList<>();
|
||||||
return mapObjects[chunkX][chunkY];
|
return mapObjects[chunkX][chunkY];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +84,7 @@ public class PointOfInterestMap implements SaveFileContent {
|
|||||||
mapObjects = new List[numberOfChunksX][numberOfChunksY];
|
mapObjects = new List[numberOfChunksX][numberOfChunksY];
|
||||||
for (int x = 0; x < numberOfChunksX; x++) {
|
for (int x = 0; x < numberOfChunksX; x++) {
|
||||||
for (int y = 0; y < numberOfChunksY; y++) {
|
for (int y = 0; y < numberOfChunksY; y++) {
|
||||||
mapObjects[x][y] = new ArrayList();
|
mapObjects[x][y] = new ArrayList<>();
|
||||||
int arraySize=data.readInt("mapObjects["+x +"]["+y+"]");
|
int arraySize=data.readInt("mapObjects["+x +"]["+y+"]");
|
||||||
for(int i=0;i<arraySize;i++)
|
for(int i=0;i<arraySize;i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -257,7 +257,7 @@ public class ArenaScene extends UIScene implements IAfterMatch {
|
|||||||
Array<Reward> data = new Array<>();
|
Array<Reward> data = new Array<>();
|
||||||
for (int i = 0; i < roundsWon; i++) {
|
for (int i = 0; i < roundsWon; i++) {
|
||||||
for (int j = 0; j < arenaData.rewards[i].length; j++) {
|
for (int j = 0; j < arenaData.rewards[i].length; j++) {
|
||||||
data.addAll(arenaData.rewards[i][j].generate(false, null));
|
data.addAll(arenaData.rewards[i][j].generate(false, null, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RewardScene.instance().loadRewards(data, RewardScene.Type.Loot, null);
|
RewardScene.instance().loadRewards(data, RewardScene.Type.Loot, null);
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ import com.github.tommyettinger.textra.TextraLabel;
|
|||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.adventure.data.DifficultyData;
|
import forge.adventure.data.DifficultyData;
|
||||||
import forge.adventure.data.HeroListData;
|
import forge.adventure.data.HeroListData;
|
||||||
import forge.adventure.util.AdventureModes;
|
import forge.adventure.util.*;
|
||||||
import forge.adventure.util.Config;
|
|
||||||
import forge.adventure.util.Selector;
|
|
||||||
import forge.adventure.util.UIActor;
|
|
||||||
import forge.adventure.world.WorldSave;
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package forge.adventure.scene;
|
package forge.adventure.scene;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||||
@@ -50,6 +49,7 @@ public class PlayerStatisticScene extends UIScene {
|
|||||||
Table root;
|
Table root;
|
||||||
boolean toggle = false;
|
boolean toggle = false;
|
||||||
AchievementCollection planeswalkers, achievements;
|
AchievementCollection planeswalkers, achievements;
|
||||||
|
Scene lastGameScene;
|
||||||
|
|
||||||
private PlayerStatisticScene() {
|
private PlayerStatisticScene() {
|
||||||
super(Forge.isLandscapeMode() ? "ui/statistic.json" : "ui/statistic_portrait.json");
|
super(Forge.isLandscapeMode() ? "ui/statistic.json" : "ui/statistic_portrait.json");
|
||||||
@@ -59,10 +59,10 @@ public class PlayerStatisticScene extends UIScene {
|
|||||||
scrollContainer.row();
|
scrollContainer.row();
|
||||||
achievementContainer = new Table(Controls.getSkin());
|
achievementContainer = new Table(Controls.getSkin());
|
||||||
blessingScroll = Controls.newTextraLabel("");
|
blessingScroll = Controls.newTextraLabel("");
|
||||||
blessingScroll.setColor(Color.BLACK);
|
|
||||||
blessingScroll.setAlignment(Align.topLeft);
|
blessingScroll.setAlignment(Align.topLeft);
|
||||||
blessingScroll.setWrap(true);
|
blessingScroll.setWrap(true);
|
||||||
ui.onButtonPress("return", PlayerStatisticScene.this::back);
|
ui.onButtonPress("return", PlayerStatisticScene.this::back);
|
||||||
|
ui.onButtonPress("quests", PlayerStatisticScene.this::quests);
|
||||||
avatar = ui.findActor("avatar");
|
avatar = ui.findActor("avatar");
|
||||||
avatarBorder = ui.findActor("avatarBorder");
|
avatarBorder = ui.findActor("avatarBorder");
|
||||||
playerName = ui.findActor("playerName");
|
playerName = ui.findActor("playerName");
|
||||||
@@ -104,13 +104,14 @@ public class PlayerStatisticScene extends UIScene {
|
|||||||
|
|
||||||
private static PlayerStatisticScene object;
|
private static PlayerStatisticScene object;
|
||||||
|
|
||||||
public static PlayerStatisticScene instance() {
|
public static PlayerStatisticScene instance(Scene lastGameScene) {
|
||||||
if (object == null)
|
if (object == null)
|
||||||
object = new PlayerStatisticScene();
|
object = new PlayerStatisticScene();
|
||||||
|
if (lastGameScene != null)
|
||||||
|
object.lastGameScene=lastGameScene;
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (achievements != null) {
|
if (achievements != null) {
|
||||||
@@ -243,4 +244,16 @@ public class PlayerStatisticScene extends UIScene {
|
|||||||
achievementContainer.row();
|
achievementContainer.row();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean quests() {
|
||||||
|
Forge.switchScene(QuestLogScene.instance(lastGameScene),true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean back(){
|
||||||
|
Forge.switchScene(lastGameScene==null?GameScene.instance():lastGameScene);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
240
forge-gui-mobile/src/forge/adventure/scene/QuestLogScene.java
Normal file
240
forge-gui-mobile/src/forge/adventure/scene/QuestLogScene.java
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
package forge.adventure.scene;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Touchable;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.*;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
|
||||||
|
import com.badlogic.gdx.utils.Align;
|
||||||
|
import com.github.tommyettinger.textra.TextraButton;
|
||||||
|
import com.github.tommyettinger.textra.TypingLabel;
|
||||||
|
import forge.Forge;
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
|
import forge.adventure.data.AdventureQuestStage;
|
||||||
|
import forge.adventure.stage.MapStage;
|
||||||
|
import forge.adventure.util.AdventureQuestController;
|
||||||
|
import forge.adventure.util.Controls;
|
||||||
|
import forge.adventure.util.Current;
|
||||||
|
|
||||||
|
public class QuestLogScene extends UIScene {
|
||||||
|
private Table scrollContainer, detailScrollContainer;
|
||||||
|
Window scrollWindow;
|
||||||
|
ScrollPane scroller,detailScroller;
|
||||||
|
Table root, detailRoot;
|
||||||
|
TextraButton trackButton, backToListButton, abandonQuestButton;
|
||||||
|
Scene lastGameScene;
|
||||||
|
|
||||||
|
private QuestLogScene() {
|
||||||
|
super(Forge.isLandscapeMode() ? "ui/quests.json" : "ui/quests_portrait.json");
|
||||||
|
|
||||||
|
|
||||||
|
scrollWindow = ui.findActor("scrollWindow");
|
||||||
|
root = ui.findActor("questList");
|
||||||
|
detailRoot = ui.findActor("questDetails");
|
||||||
|
abandonQuestButton = ui.findActor("abandonQuest");
|
||||||
|
trackButton = ui.findActor("trackQuest");
|
||||||
|
backToListButton = ui.findActor("backToList");//Controls.newTextButton("Quest List");
|
||||||
|
ui.onButtonPress("return", QuestLogScene.this::back);
|
||||||
|
ui.onButtonPress("status", QuestLogScene.this::status);
|
||||||
|
ui.onButtonPress("backToList", QuestLogScene.this::backToList);
|
||||||
|
|
||||||
|
|
||||||
|
//Todo - refactor below, replace buttons in landscape
|
||||||
|
|
||||||
|
scrollContainer = new Table(Controls.getSkin());
|
||||||
|
scrollContainer.row();
|
||||||
|
|
||||||
|
detailScrollContainer = new Table(Controls.getSkin());
|
||||||
|
detailScrollContainer.row();
|
||||||
|
|
||||||
|
detailScroller = new ScrollPane(detailScrollContainer);
|
||||||
|
detailRoot.row();
|
||||||
|
detailRoot.add(detailScroller).expandX().fillX();
|
||||||
|
detailRoot.row();
|
||||||
|
scrollWindow.setTouchable(Touchable.disabled);
|
||||||
|
detailRoot.setVisible(false);
|
||||||
|
scroller = new ScrollPane(scrollContainer);
|
||||||
|
root.add(scroller).colspan(3);
|
||||||
|
root.align(Align.right);
|
||||||
|
root.row();
|
||||||
|
Label column0Label = new Label("Quest Name", Controls.getSkin());
|
||||||
|
column0Label.setColor(Color.BLACK);
|
||||||
|
root.add(column0Label).align(Align.bottomLeft);
|
||||||
|
root.row();
|
||||||
|
ScrollPane scroller = new ScrollPane(scrollContainer);
|
||||||
|
root.add(scroller).colspan(3).fill().expand();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static QuestLogScene object;
|
||||||
|
|
||||||
|
public static QuestLogScene instance(Scene lastGameScene) {
|
||||||
|
//if (object == null)
|
||||||
|
object = new QuestLogScene();
|
||||||
|
if (lastGameScene != null)
|
||||||
|
object.lastGameScene=lastGameScene;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enter() {
|
||||||
|
super.enter();
|
||||||
|
buildList();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildList(){
|
||||||
|
backToList();
|
||||||
|
|
||||||
|
scrollContainer.clear();
|
||||||
|
|
||||||
|
for (AdventureQuestData quest : Current.player().getQuests()) {
|
||||||
|
TypingLabel nameLabel = Controls.newTypingLabel(quest.getName());
|
||||||
|
nameLabel.skipToTheEnd();
|
||||||
|
nameLabel.setWrap(true);
|
||||||
|
nameLabel.setColor(Color.BLACK);
|
||||||
|
scrollContainer.add(nameLabel).align(Align.left).expandX();
|
||||||
|
Button details = Controls.newTextButton("Details");
|
||||||
|
details.addListener( new ClickListener(){
|
||||||
|
public void clicked(InputEvent event, float x, float y){
|
||||||
|
loadDetailsPane(quest);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scrollContainer.add(details).align(Align.center).padRight(10);
|
||||||
|
scrollContainer.row().padTop(5);
|
||||||
|
addToSelectable(details);
|
||||||
|
}
|
||||||
|
performTouch(scrollPaneOfActor(scrollContainer)); //can use mouse wheel if available to scroll
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backToList(){
|
||||||
|
abandonQuestButton.setVisible(false);
|
||||||
|
trackButton.setVisible(false);
|
||||||
|
backToListButton.setVisible(false);
|
||||||
|
|
||||||
|
root.setVisible(true);
|
||||||
|
detailRoot.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDetailsPane(AdventureQuestData quest){
|
||||||
|
if (quest == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
root.setVisible(false);
|
||||||
|
detailRoot.setVisible(true);
|
||||||
|
detailScrollContainer.row();
|
||||||
|
trackButton.setText(quest.isTracked?"Untrack Quest":"Track Quest");
|
||||||
|
trackButton.addListener( new ClickListener(){
|
||||||
|
public void clicked(InputEvent event, float x, float y){
|
||||||
|
toggleTracked(quest);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
abandonQuestButton.setColor(Color.RED);
|
||||||
|
abandonQuestButton.addListener( new ClickListener(){
|
||||||
|
public void clicked(InputEvent event, float x, float y){
|
||||||
|
|
||||||
|
Dialog confirm = createGenericDialog("", "Abandon Quest?","Yes","No", () -> abandonQuest(quest), null);
|
||||||
|
showDialog(confirm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
TypingLabel dNameLabel = Controls.newTypingLabel(quest.getName());
|
||||||
|
dNameLabel.skipToTheEnd();
|
||||||
|
dNameLabel.setWrap(true);
|
||||||
|
dNameLabel.setColor(Color.BLACK);
|
||||||
|
|
||||||
|
detailScrollContainer.add(dNameLabel).align(Align.left).expandX().padLeft(10);
|
||||||
|
|
||||||
|
abandonQuestButton.setVisible(!quest.storyQuest);
|
||||||
|
trackButton.setVisible(true);
|
||||||
|
backToListButton.setVisible(true);
|
||||||
|
|
||||||
|
TypingLabel dDescriptionLabel = Controls.newTypingLabel(quest.getDescription());
|
||||||
|
dDescriptionLabel.skipToTheEnd();
|
||||||
|
dDescriptionLabel.setWrap(true);
|
||||||
|
dDescriptionLabel.setColor(Color.DARK_GRAY);
|
||||||
|
|
||||||
|
detailScrollContainer.row();
|
||||||
|
detailScrollContainer.add(dDescriptionLabel).align(Align.left).padLeft(25);
|
||||||
|
|
||||||
|
for (AdventureQuestStage stage : quest.getStagesForQuestLog()){
|
||||||
|
// Todo: Eventually needs to be multiple loops or sort stages by status
|
||||||
|
// because parallel objectives will make this messy
|
||||||
|
switch (stage.getStatus()){
|
||||||
|
case Complete:
|
||||||
|
TypingLabel completeLabel = Controls.newTypingLabel("* " + stage.name);
|
||||||
|
completeLabel.skipToTheEnd();
|
||||||
|
completeLabel.setColor(Color.GREEN);
|
||||||
|
completeLabel.setWrap(true);
|
||||||
|
detailScrollContainer.row();
|
||||||
|
detailScrollContainer.add(completeLabel).align(Align.left).padLeft(25);
|
||||||
|
break;
|
||||||
|
case Failed:
|
||||||
|
TypingLabel failedLabel = Controls.newTypingLabel("* " + stage.name);
|
||||||
|
failedLabel.skipToTheEnd();
|
||||||
|
failedLabel.setColor(Color.RED);
|
||||||
|
failedLabel.setText(stage.name);
|
||||||
|
failedLabel.setWrap(true);
|
||||||
|
detailScrollContainer.row();
|
||||||
|
detailScrollContainer.add(failedLabel).align(Align.left).padLeft(25);
|
||||||
|
break;
|
||||||
|
case Active:
|
||||||
|
TypingLabel activeLabel = Controls.newTypingLabel("* " + stage.name);
|
||||||
|
activeLabel.skipToTheEnd();
|
||||||
|
activeLabel.setColor(Color.BLACK);
|
||||||
|
activeLabel.setWrap(true);
|
||||||
|
detailScrollContainer.row();
|
||||||
|
detailScrollContainer.add(activeLabel).align(Align.left).padLeft(25);
|
||||||
|
|
||||||
|
TypingLabel activeDescriptionLabel = Controls.newTypingLabel(stage.description);
|
||||||
|
activeDescriptionLabel.skipToTheEnd();
|
||||||
|
activeDescriptionLabel.setColor(Color.DARK_GRAY);
|
||||||
|
activeDescriptionLabel.setWrap(true);
|
||||||
|
|
||||||
|
detailScrollContainer.row();
|
||||||
|
detailScrollContainer.add(activeDescriptionLabel).padLeft(35).width(scrollWindow.getWidth() - 50).colspan(4);
|
||||||
|
detailScrollContainer.row();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleTracked(AdventureQuestData quest){
|
||||||
|
quest.isTracked = !quest.isTracked;
|
||||||
|
if (quest.isTracked){
|
||||||
|
for (AdventureQuestData q: Current.player().getQuests()){
|
||||||
|
if (q.equals(quest))
|
||||||
|
continue;
|
||||||
|
q.isTracked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trackButton.setText(quest.isTracked?"Untrack Quest":"Track Quest");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void status() {
|
||||||
|
Forge.switchScene(PlayerStatisticScene.instance(lastGameScene),true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean back(){
|
||||||
|
//Needed so long as quest log and stats are separate scenes that link to each other
|
||||||
|
Forge.switchScene(lastGameScene==null?GameScene.instance():lastGameScene);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void abandonQuest(AdventureQuestData quest) {
|
||||||
|
AdventureQuestController.instance().abandon(quest);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
||||||
|
buildList();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -44,7 +44,8 @@ public class RewardScene extends UIScene {
|
|||||||
private boolean showTooltips = false;
|
private boolean showTooltips = false;
|
||||||
public enum Type {
|
public enum Type {
|
||||||
Shop,
|
Shop,
|
||||||
Loot
|
Loot,
|
||||||
|
QuestReward
|
||||||
}
|
}
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
@@ -146,15 +147,16 @@ public class RewardScene extends UIScene {
|
|||||||
showLootOrDone();
|
showLootOrDone();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Shop:
|
case Shop:
|
||||||
doneButton.setText(Forge.getLocalizer().getMessage("lblLeave"));
|
doneButton.setText(Forge.getLocalizer().getMessage("lblLeave"));
|
||||||
break;
|
break;
|
||||||
case Loot:
|
case QuestReward:
|
||||||
doneButton.setText(Forge.getLocalizer().getMessage("lblDone"));
|
case Loot:
|
||||||
break;
|
doneButton.setText(Forge.getLocalizer().getMessage("lblDone"));
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
shown = false;
|
shown = false;
|
||||||
clearGenerated();
|
clearGenerated();
|
||||||
@@ -169,6 +171,8 @@ public class RewardScene extends UIScene {
|
|||||||
RewardActor reward = (RewardActor) actor;
|
RewardActor reward = (RewardActor) actor;
|
||||||
if (type == Type.Loot)
|
if (type == Type.Loot)
|
||||||
AdventurePlayer.current().addReward(reward.getReward());
|
AdventurePlayer.current().addReward(reward.getReward());
|
||||||
|
if (type == Type.QuestReward)
|
||||||
|
AdventurePlayer.current().addReward(reward.getReward()); // Want to customize this soon to have selectable rewards which will be handled different here
|
||||||
reward.clearHoldToolTip();
|
reward.clearHoldToolTip();
|
||||||
try {
|
try {
|
||||||
stage.getActors().removeValue(reward, true);
|
stage.getActors().removeValue(reward, true);
|
||||||
@@ -181,7 +185,7 @@ public class RewardScene extends UIScene {
|
|||||||
stage.act(delta);
|
stage.act(delta);
|
||||||
ImageCache.allowSingleLoad();
|
ImageCache.allowSingleLoad();
|
||||||
if (doneClicked) {
|
if (doneClicked) {
|
||||||
if (type == Type.Loot) {
|
if (type == Type.Loot || type == Type.QuestReward) {
|
||||||
flipCountDown -= Gdx.graphics.getDeltaTime();
|
flipCountDown -= Gdx.graphics.getDeltaTime();
|
||||||
exitCountDown += Gdx.graphics.getDeltaTime();
|
exitCountDown += Gdx.graphics.getDeltaTime();
|
||||||
}
|
}
|
||||||
@@ -212,7 +216,7 @@ public class RewardScene extends UIScene {
|
|||||||
}
|
}
|
||||||
if (exit)
|
if (exit)
|
||||||
done(true);
|
done(true);
|
||||||
else if (type == Type.Loot && !shown) {
|
else if ((type == Type.Loot || type == Type.QuestReward) && !shown) {
|
||||||
shown = true;
|
shown = true;
|
||||||
float delay = 0.09f;
|
float delay = 0.09f;
|
||||||
generated.shuffle();
|
generated.shuffle();
|
||||||
@@ -268,7 +272,7 @@ public class RewardScene extends UIScene {
|
|||||||
long shopSeed = changes.getShopSeed(shopActor.getObjectId());
|
long shopSeed = changes.getShopSeed(shopActor.getObjectId());
|
||||||
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(shopSeed);
|
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(shopSeed);
|
||||||
for (RewardData rdata : new Array.ArrayIterator<>(data.rewards)) {
|
for (RewardData rdata : new Array.ArrayIterator<>(data.rewards)) {
|
||||||
ret.addAll(rdata.generate(false));
|
ret.addAll(rdata.generate(false, false));
|
||||||
}
|
}
|
||||||
shopActor.setRewardData(ret);
|
shopActor.setRewardData(ret);
|
||||||
loadRewards(ret, RewardScene.Type.Shop,shopActor);
|
loadRewards(ret, RewardScene.Type.Shop,shopActor);
|
||||||
@@ -343,6 +347,7 @@ public class RewardScene extends UIScene {
|
|||||||
restockButton.setDisabled(true);
|
restockButton.setDisabled(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QuestReward:
|
||||||
case Loot:
|
case Loot:
|
||||||
shopNameLabel.setVisible(false);
|
shopNameLabel.setVisible(false);
|
||||||
shopNameLabel.setText("");
|
shopNameLabel.setText("");
|
||||||
@@ -424,7 +429,9 @@ public class RewardScene extends UIScene {
|
|||||||
if (lastRowCount != 0)
|
if (lastRowCount != 0)
|
||||||
lastRowXAdjust = ((numberOfColumns * cardWidth) - (lastRowCount * cardWidth)) / 2;
|
lastRowXAdjust = ((numberOfColumns * cardWidth) - (lastRowCount * cardWidth)) / 2;
|
||||||
}
|
}
|
||||||
RewardActor actor = new RewardActor(reward, type == Type.Loot, type);
|
|
||||||
|
RewardActor actor = new RewardActor(reward, type == Type.Loot || type == Type.QuestReward,type);
|
||||||
|
|
||||||
actor.setBounds(lastRowXAdjust + xOff + cardWidth * (i % numberOfColumns) + spacing, yOff + cardHeight * currentRow + spacing, cardWidth - spacing * 2, cardHeight - spacing * 2);
|
actor.setBounds(lastRowXAdjust + xOff + cardWidth * (i % numberOfColumns) + spacing, yOff + cardHeight * currentRow + spacing, cardWidth - spacing * 2, cardHeight - spacing * 2);
|
||||||
|
|
||||||
if (type == Type.Shop) {
|
if (type == Type.Shop) {
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ import forge.Forge;
|
|||||||
import forge.adventure.pointofintrest.PointOfInterest;
|
import forge.adventure.pointofintrest.PointOfInterest;
|
||||||
import forge.adventure.stage.MapStage;
|
import forge.adventure.stage.MapStage;
|
||||||
import forge.adventure.stage.PointOfInterestMapRenderer;
|
import forge.adventure.stage.PointOfInterestMapRenderer;
|
||||||
import forge.adventure.util.Config;
|
import forge.adventure.util.*;
|
||||||
import forge.adventure.util.Current;
|
|
||||||
import forge.adventure.util.Paths;
|
|
||||||
import forge.adventure.util.TemplateTmxMapLoader;
|
|
||||||
import forge.adventure.world.WorldSave;
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.sound.SoundEffectType;
|
import forge.sound.SoundEffectType;
|
||||||
import forge.sound.SoundSystem;
|
import forge.sound.SoundSystem;
|
||||||
@@ -97,9 +94,14 @@ public class TileMapScene extends HudScene {
|
|||||||
if (Current.player().fullHeal())
|
if (Current.player().fullHeal())
|
||||||
autoheal = true; // to play sound/effect on act
|
autoheal = true; // to play sound/effect on act
|
||||||
}
|
}
|
||||||
|
AdventureQuestController.instance().updateEnteredPOI(rootPoint);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(stage);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load(PointOfInterest point) {
|
public void load(PointOfInterest point) {
|
||||||
|
AdventureQuestController.instance().mostRecentPOI = point;
|
||||||
rootPoint = point;
|
rootPoint = point;
|
||||||
oldMap = point.getData().map;
|
oldMap = point.getData().map;
|
||||||
map = new TemplateTmxMapLoader().load(Config.instance().getFilePath(point.getData().map));
|
map = new TemplateTmxMapLoader().load(Config.instance().getFilePath(point.getData().map));
|
||||||
@@ -115,7 +117,7 @@ public class TileMapScene extends HudScene {
|
|||||||
return AUTO_HEAL_LOCATIONS.contains(rootPoint.getData().type);
|
return AUTO_HEAL_LOCATIONS.contains(rootPoint.getData().type);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointOfInterest rootPoint;
|
public PointOfInterest rootPoint;
|
||||||
String oldMap;
|
String oldMap;
|
||||||
|
|
||||||
private void load(String targetMap) {
|
private void load(String targetMap) {
|
||||||
|
|||||||
@@ -157,6 +157,18 @@ public class ConsoleCommandInterpreter {
|
|||||||
Current.player().giveGold(amount);
|
Current.player().giveGold(amount);
|
||||||
return "Added " + amount + " gold";
|
return "Added " + amount + " gold";
|
||||||
});
|
});
|
||||||
|
registerCommand(new String[]{"give", "quest"}, s -> {
|
||||||
|
if (s.length<1) return "Command needs 1 parameter: QuestID";
|
||||||
|
int ID;
|
||||||
|
try{
|
||||||
|
ID =Integer.parseInt(s[0]);
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
return "Can not convert " +s[0]+" to number";
|
||||||
|
}
|
||||||
|
Current.player().addQuest(ID);
|
||||||
|
return "Quest generated";
|
||||||
|
});
|
||||||
registerCommand(new String[]{"give", "shards"}, s -> {
|
registerCommand(new String[]{"give", "shards"}, s -> {
|
||||||
if (s.length < 1) return "Command needs 1 parameter: Amount.";
|
if (s.length < 1) return "Command needs 1 parameter: Amount.";
|
||||||
int amount;
|
int amount;
|
||||||
@@ -308,19 +320,7 @@ public class ConsoleCommandInterpreter {
|
|||||||
Current.player().addShards(value);
|
Current.player().addShards(value);
|
||||||
return "Player now has " + Current.player().getShards() + " shards";
|
return "Player now has " + Current.player().getShards() + " shards";
|
||||||
});
|
});
|
||||||
// registerCommand(new String[]{"getMana", "percent"}, s -> {
|
registerCommand(new String[]{"debug","map"}, s -> {
|
||||||
// if(s.length<1) return "Command needs 1 parameter: Amount";
|
|
||||||
// float value = 0;
|
|
||||||
// try { value = Float.parseFloat(s[0]); }
|
|
||||||
// catch (Exception e) { return "Can not convert " + s[0] + " to integer"; }
|
|
||||||
// Current.player().addManaPercent(value);
|
|
||||||
// return "Player healed to " + Current.player().getLife() + "/" + Current.player().getMaxLife();
|
|
||||||
// });
|
|
||||||
// registerCommand(new String[]{"getMana", "full"}, s -> {
|
|
||||||
// Current.player().addManaPercent(1.0f);
|
|
||||||
// return "Player healed to " + Current.player().getLife() + "/" + Current.player().getMaxLife();
|
|
||||||
// });
|
|
||||||
registerCommand(new String[]{"debug", "map"}, s -> {
|
|
||||||
GameHUD.getInstance().setDebug(true);
|
GameHUD.getInstance().setDebug(true);
|
||||||
return "Debug map ON";
|
return "Debug map ON";
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public class GameHUD extends Stage {
|
|||||||
private final TextraLabel lifePoints, money, shards, keys;
|
private final TextraLabel lifePoints, money, shards, keys;
|
||||||
private final Image miniMap, gamehud, mapborder, avatarborder, blank;
|
private final Image miniMap, gamehud, mapborder, avatarborder, blank;
|
||||||
private final InputEvent eventTouchDown, eventTouchUp;
|
private final InputEvent eventTouchDown, eventTouchUp;
|
||||||
private final TextraButton deckActor, openMapActor, menuActor, statsActor, inventoryActor, exitToWorldMapActor;
|
private final TextraButton deckActor, openMapActor, menuActor, logbookActor, inventoryActor, exitToWorldMapActor;
|
||||||
public final UIActor ui;
|
public final UIActor ui;
|
||||||
private final Touchpad touchpad;
|
private final Touchpad touchpad;
|
||||||
private final Console console;
|
private final Console console;
|
||||||
@@ -83,7 +83,7 @@ public class GameHUD extends Stage {
|
|||||||
ui.onButtonPress("openmap", () -> GameHUD.this.openMap());
|
ui.onButtonPress("openmap", () -> GameHUD.this.openMap());
|
||||||
menuActor = ui.findActor("menu");
|
menuActor = ui.findActor("menu");
|
||||||
referenceX = menuActor.getX();
|
referenceX = menuActor.getX();
|
||||||
statsActor = ui.findActor("statistic");
|
logbookActor = ui.findActor("logbook");
|
||||||
inventoryActor = ui.findActor("inventory");
|
inventoryActor = ui.findActor("inventory");
|
||||||
gamehud = ui.findActor("gamehud");
|
gamehud = ui.findActor("gamehud");
|
||||||
exitToWorldMapActor = ui.findActor("exittoworldmap");
|
exitToWorldMapActor = ui.findActor("exittoworldmap");
|
||||||
@@ -115,7 +115,7 @@ public class GameHUD extends Stage {
|
|||||||
avatar = ui.findActor("avatar");
|
avatar = ui.findActor("avatar");
|
||||||
ui.onButtonPress("menu", () -> menu());
|
ui.onButtonPress("menu", () -> menu());
|
||||||
ui.onButtonPress("inventory", () -> openInventory());
|
ui.onButtonPress("inventory", () -> openInventory());
|
||||||
ui.onButtonPress("statistic", () -> statistic());
|
ui.onButtonPress("logbook", () -> logbook());
|
||||||
ui.onButtonPress("deck", () -> openDeck());
|
ui.onButtonPress("deck", () -> openDeck());
|
||||||
ui.onButtonPress("exittoworldmap", () -> exitToWorldMap());
|
ui.onButtonPress("exittoworldmap", () -> exitToWorldMap());
|
||||||
lifePoints = ui.findActor("lifePoints");
|
lifePoints = ui.findActor("lifePoints");
|
||||||
@@ -157,8 +157,8 @@ public class GameHUD extends Stage {
|
|||||||
Forge.switchScene(MapViewScene.instance());
|
Forge.switchScene(MapViewScene.instance());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void statistic() {
|
private void logbook() {
|
||||||
Forge.switchScene(PlayerStatisticScene.instance());
|
Forge.switchScene(QuestLogScene.instance(Forge.getCurrentScene()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GameHUD getInstance() {
|
public static GameHUD getInstance() {
|
||||||
@@ -222,7 +222,7 @@ public class GameHUD extends Stage {
|
|||||||
&& !(Controls.actorContainsVector(menuActor, touch)) //not inside menu button
|
&& !(Controls.actorContainsVector(menuActor, touch)) //not inside menu button
|
||||||
&& !(Controls.actorContainsVector(deckActor, touch)) //not inside deck button
|
&& !(Controls.actorContainsVector(deckActor, touch)) //not inside deck button
|
||||||
&& !(Controls.actorContainsVector(openMapActor, touch)) //not inside openmap button
|
&& !(Controls.actorContainsVector(openMapActor, touch)) //not inside openmap button
|
||||||
&& !(Controls.actorContainsVector(statsActor, touch)) //not inside stats button
|
&& !(Controls.actorContainsVector(logbookActor, touch)) //not inside stats button
|
||||||
&& !(Controls.actorContainsVector(inventoryActor, touch)) //not inside inventory button
|
&& !(Controls.actorContainsVector(inventoryActor, touch)) //not inside inventory button
|
||||||
&& !(Controls.actorContainsVector(exitToWorldMapActor, touch)) //not inside exit button
|
&& !(Controls.actorContainsVector(exitToWorldMapActor, touch)) //not inside exit button
|
||||||
&& (Controls.actorContainsVector(ui, touch)) //inside display bounds
|
&& (Controls.actorContainsVector(ui, touch)) //inside display bounds
|
||||||
@@ -503,7 +503,7 @@ public class GameHUD extends Stage {
|
|||||||
setAlpha(avatar, visible);
|
setAlpha(avatar, visible);
|
||||||
setAlpha(deckActor, visible);
|
setAlpha(deckActor, visible);
|
||||||
setAlpha(menuActor, visible);
|
setAlpha(menuActor, visible);
|
||||||
setAlpha(statsActor, visible);
|
setAlpha(logbookActor, visible);
|
||||||
setAlpha(inventoryActor, visible);
|
setAlpha(inventoryActor, visible);
|
||||||
setAlpha(exitToWorldMapActor, visible);
|
setAlpha(exitToWorldMapActor, visible);
|
||||||
opacity = visible ? 1f : 0.4f;
|
opacity = visible ? 1f : 0.4f;
|
||||||
@@ -579,7 +579,7 @@ public class GameHUD extends Stage {
|
|||||||
isHiding = true;
|
isHiding = true;
|
||||||
deckActor.addAction(Actions.sequence(Actions.fadeOut(0.10f), Actions.hide(), Actions.moveTo(deckActor.getX() + deckActor.getWidth(), deckActor.getY())));
|
deckActor.addAction(Actions.sequence(Actions.fadeOut(0.10f), Actions.hide(), Actions.moveTo(deckActor.getX() + deckActor.getWidth(), deckActor.getY())));
|
||||||
inventoryActor.addAction(Actions.sequence(Actions.fadeOut(0.15f), Actions.hide(), Actions.moveTo(inventoryActor.getX() + inventoryActor.getWidth(), inventoryActor.getY())));
|
inventoryActor.addAction(Actions.sequence(Actions.fadeOut(0.15f), Actions.hide(), Actions.moveTo(inventoryActor.getX() + inventoryActor.getWidth(), inventoryActor.getY())));
|
||||||
statsActor.addAction(Actions.sequence(Actions.fadeOut(0.20f), Actions.hide(), Actions.moveTo(statsActor.getX() + statsActor.getWidth(), statsActor.getY())));
|
logbookActor.addAction(Actions.sequence(Actions.fadeOut(0.20f), Actions.hide(), Actions.moveTo(logbookActor.getX() + logbookActor.getWidth(), logbookActor.getY())));
|
||||||
menuActor.addAction(Actions.sequence(Actions.fadeOut(0.25f), Actions.hide(), Actions.moveTo(menuActor.getX() + menuActor.getWidth(), menuActor.getY())));
|
menuActor.addAction(Actions.sequence(Actions.fadeOut(0.25f), Actions.hide(), Actions.moveTo(menuActor.getX() + menuActor.getWidth(), menuActor.getY())));
|
||||||
if (GameScene.instance().isNotInWorldMap())
|
if (GameScene.instance().isNotInWorldMap())
|
||||||
exitToWorldMapActor.addAction(Actions.sequence(Actions.fadeOut(0.2f), Actions.hide(), Actions.moveTo(exitToWorldMapActor.getX() + exitToWorldMapActor.getWidth(), exitToWorldMapActor.getY())));
|
exitToWorldMapActor.addAction(Actions.sequence(Actions.fadeOut(0.2f), Actions.hide(), Actions.moveTo(exitToWorldMapActor.getX() + exitToWorldMapActor.getWidth(), exitToWorldMapActor.getY())));
|
||||||
@@ -595,7 +595,7 @@ public class GameHUD extends Stage {
|
|||||||
return;
|
return;
|
||||||
isShowing = true;
|
isShowing = true;
|
||||||
menuActor.addAction(Actions.sequence(Actions.delay(0.1f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, menuActor.getY(), 0.25f))));
|
menuActor.addAction(Actions.sequence(Actions.delay(0.1f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, menuActor.getY(), 0.25f))));
|
||||||
statsActor.addAction(Actions.sequence(Actions.delay(0.15f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, statsActor.getY(), 0.25f))));
|
logbookActor.addAction(Actions.sequence(Actions.delay(0.15f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, logbookActor.getY(), 0.25f))));
|
||||||
inventoryActor.addAction(Actions.sequence(Actions.delay(0.2f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, inventoryActor.getY(), 0.25f))));
|
inventoryActor.addAction(Actions.sequence(Actions.delay(0.2f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, inventoryActor.getY(), 0.25f))));
|
||||||
deckActor.addAction(Actions.sequence(Actions.delay(0.25f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, deckActor.getY(), 0.25f))));
|
deckActor.addAction(Actions.sequence(Actions.delay(0.25f), Actions.parallel(Actions.show(), Actions.alpha(opacity, 0.1f), Actions.moveTo(referenceX, deckActor.getY(), 0.25f))));
|
||||||
if (GameScene.instance().isNotInWorldMap())
|
if (GameScene.instance().isNotInWorldMap())
|
||||||
|
|||||||
@@ -126,8 +126,9 @@ public class MapStage extends GameStage {
|
|||||||
public PointOfInterestChanges getChanges() {
|
public PointOfInterestChanges getChanges() {
|
||||||
return changes;
|
return changes;
|
||||||
}
|
}
|
||||||
|
private boolean matchJustEnded = false;
|
||||||
|
|
||||||
private MapStage() {
|
protected MapStage() {
|
||||||
dialog = Controls.newDialog("");
|
dialog = Controls.newDialog("");
|
||||||
eventTouchDown = new InputEvent();
|
eventTouchDown = new InputEvent();
|
||||||
eventTouchDown.setPointer(-1);
|
eventTouchDown.setPointer(-1);
|
||||||
@@ -550,7 +551,7 @@ public class MapStage extends GameStage {
|
|||||||
System.err.printf("Enemy \"%s\" not found.", enemy);
|
System.err.printf("Enemy \"%s\" not found.", enemy);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
EnemySprite mob = new EnemySprite(id, EN);
|
EnemySprite mob = new EnemySprite(id, EN, changes);
|
||||||
Object dialogObject = prop.get("dialog"); //Check if the enemy has a dialogue attached to it.
|
Object dialogObject = prop.get("dialog"); //Check if the enemy has a dialogue attached to it.
|
||||||
if (dialogObject != null && !dialogObject.toString().isEmpty()) {
|
if (dialogObject != null && !dialogObject.toString().isEmpty()) {
|
||||||
mob.dialog = new MapDialog(dialogObject.toString(), this, mob.getId());
|
mob.dialog = new MapDialog(dialogObject.toString(), this, mob.getId());
|
||||||
@@ -644,28 +645,17 @@ public class MapStage extends GameStage {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "quest":
|
case "quest":
|
||||||
DialogActor dialog;
|
|
||||||
if (prop.containsKey("questtype")) {
|
if (prop.containsKey("questtype")) {
|
||||||
TiledMapTileMapObject tiledObj = (TiledMapTileMapObject) obj;
|
TiledMapTileMapObject tiledObj = (TiledMapTileMapObject) obj;
|
||||||
|
|
||||||
String questOrigin = prop.containsKey("questtype") ? prop.get("questtype").toString() : "";
|
String questOrigin = prop.containsKey("questtype") ? prop.get("questtype").toString() : "";
|
||||||
|
AdventureQuestData questInfo = AdventureQuestController.instance().getQuestNPCResponse(TileMapScene.instance().rootPoint.getID(), changes,questOrigin);
|
||||||
|
|
||||||
String placeholderText = "[" +
|
if (questInfo != null) {
|
||||||
" {" +
|
DialogActor questActor = new DialogActor(questInfo, this, id);
|
||||||
" \"name\":\"Quest Offer\"," +
|
questActor.setVisible(false);
|
||||||
" \"text\":\"Please, help us!\\n((QUEST DESCRIPTION))\"," +
|
addMapActor(obj, questActor);
|
||||||
" \"condition\":[]," +
|
|
||||||
" \"options\":[" +
|
|
||||||
" { \"name\":\"No, I'm not ready yet.\nMaybe next snapshot.\" }," +
|
|
||||||
" ]" +
|
|
||||||
" }" +
|
|
||||||
"]";
|
|
||||||
|
|
||||||
{
|
|
||||||
dialog = new DialogActor(this, id, placeholderText, tiledObj.getTextureRegion());
|
|
||||||
}
|
}
|
||||||
dialog.setVisible(false);
|
|
||||||
addMapActor(obj, dialog);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -757,7 +747,7 @@ public class MapStage extends GameStage {
|
|||||||
Array<Reward> ret = new Array<>();
|
Array<Reward> ret = new Array<>();
|
||||||
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(changes.getShopSeed(id));
|
WorldSave.getCurrentSave().getWorld().getRandom().setSeed(changes.getShopSeed(id));
|
||||||
for (RewardData rdata : new Array.ArrayIterator<>(data.rewards)) {
|
for (RewardData rdata : new Array.ArrayIterator<>(data.rewards)) {
|
||||||
ret.addAll(rdata.generate(false));
|
ret.addAll(rdata.generate(false, false));
|
||||||
}
|
}
|
||||||
ShopActor actor = new ShopActor(this, id, ret, data);
|
ShopActor actor = new ShopActor(this, id, ret, data);
|
||||||
addMapActor(obj, actor);
|
addMapActor(obj, actor);
|
||||||
@@ -787,6 +777,8 @@ public class MapStage extends GameStage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean exitDungeon() {
|
public boolean exitDungeon() {
|
||||||
|
AdventureQuestController.instance().updateQuestsLeave();
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(this);
|
||||||
isLoadingMatch = false;
|
isLoadingMatch = false;
|
||||||
effect = null; //Reset dungeon effects.
|
effect = null; //Reset dungeon effects.
|
||||||
clearIsInMap();
|
clearIsInMap();
|
||||||
@@ -809,6 +801,9 @@ public class MapStage extends GameStage {
|
|||||||
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
|
currentMob.setAnimation(CharacterSprite.AnimationTypes.Death);
|
||||||
currentMob.resetCollisionHeight();
|
currentMob.resetCollisionHeight();
|
||||||
startPause(0.3f, MapStage.this::getReward);
|
startPause(0.3f, MapStage.this::getReward);
|
||||||
|
AdventureQuestController.instance().updateQuestsWin(currentMob,enemies);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.this);
|
||||||
|
player.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
||||||
}
|
}
|
||||||
}, 1f);
|
}, 1f);
|
||||||
} else {
|
} else {
|
||||||
@@ -821,6 +816,8 @@ public class MapStage extends GameStage {
|
|||||||
currentMob.resetCollisionHeight();
|
currentMob.resetCollisionHeight();
|
||||||
player.setPosition(oldPosition4);
|
player.setPosition(oldPosition4);
|
||||||
currentMob.freezeMovement();
|
currentMob.freezeMovement();
|
||||||
|
AdventureQuestController.instance().updateQuestsLose(currentMob);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.this);
|
||||||
boolean defeated = Current.player().defeated();
|
boolean defeated = Current.player().defeated();
|
||||||
if (canFailDungeon && defeated) {
|
if (canFailDungeon && defeated) {
|
||||||
//If hardcore mode is added, check and redirect to game over screen here
|
//If hardcore mode is added, check and redirect to game over screen here
|
||||||
@@ -919,41 +916,37 @@ public class MapStage extends GameStage {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActing(float delta) {
|
protected void onActing(float delta) {
|
||||||
|
if (isPaused() || isDialogOnlyInput())
|
||||||
|
return;
|
||||||
Iterator<EnemySprite> it = enemies.iterator();
|
Iterator<EnemySprite> it = enemies.iterator();
|
||||||
while (it.hasNext()) {
|
|
||||||
EnemySprite mob = it.next();
|
|
||||||
mob.updatePositon();
|
|
||||||
mob.targetVector = mob.getTargetVector(player, delta);
|
|
||||||
Vector2 currentVector = new Vector2(mob.targetVector);
|
|
||||||
mob.clearActions();
|
|
||||||
if (mob.targetVector.len() == 0.0f) {
|
|
||||||
mob.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mob.getData().flying)//if direct path is not possible
|
if (!matchJustEnded) {
|
||||||
{
|
while (it.hasNext()) {
|
||||||
//Todo: fix below for collision logic
|
EnemySprite mob = it.next();
|
||||||
float safeLen = lengthWithoutCollision(mob, mob.targetVector);
|
mob.updatePositon();
|
||||||
if (safeLen > 0.1f) {
|
mob.targetVector = mob.getTargetVector(player, delta);
|
||||||
currentVector.setLength(Math.min(safeLen, mob.targetVector.len()));
|
Vector2 currentVector = new Vector2(mob.targetVector);
|
||||||
} else {
|
mob.clearActions();
|
||||||
currentVector = Vector2.Zero;
|
if (mob.targetVector.len() == 0.0f) {
|
||||||
|
mob.setAnimation(CharacterSprite.AnimationTypes.Idle);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mob.getData().flying)//if direct path is not possible
|
||||||
|
{
|
||||||
|
//Todo: fix below for collision logic
|
||||||
|
float safeLen = lengthWithoutCollision(mob, mob.targetVector);
|
||||||
|
if (safeLen > 0.1f) {
|
||||||
|
currentVector.setLength(Math.min(safeLen, mob.targetVector.len()));
|
||||||
|
} else {
|
||||||
|
currentVector = Vector2.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentVector.setLength(Math.min(mob.speed() * delta, mob.targetVector.len()));
|
||||||
|
mob.moveBy(currentVector.x, currentVector.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//mob.targetVector.setLength(Math.min(mob.speed() * delta, mob.targetVector.len()));
|
|
||||||
// if (mob.targetVector.len() < 0.3f) {
|
|
||||||
// mob.targetVector = Vector2.Zero;
|
|
||||||
// }
|
|
||||||
currentVector.setLength(Math.min(mob.speed() * delta, mob.targetVector.len()));
|
|
||||||
//if (destination.len() < 0.3f) destination = Vector2.Zero;
|
|
||||||
mob.moveBy(currentVector.x, currentVector.y);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
float sprintingMod = currentModifications.containsKey(PlayerModification.Sprint) ? 2 : 1;
|
float sprintingMod = currentModifications.containsKey(PlayerModification.Sprint) ? 2 : 1;
|
||||||
player.setMoveModifier(2 * sprintingMod);
|
player.setMoveModifier(2 * sprintingMod);
|
||||||
oldPosition4.set(oldPosition3);
|
oldPosition4.set(oldPosition3);
|
||||||
@@ -965,6 +958,7 @@ public class MapStage extends GameStage {
|
|||||||
if (actor instanceof EnemySprite) {
|
if (actor instanceof EnemySprite) {
|
||||||
EnemySprite mob = (EnemySprite) actor;
|
EnemySprite mob = (EnemySprite) actor;
|
||||||
currentMob = mob;
|
currentMob = mob;
|
||||||
|
currentMob.clearCollisionHeight();
|
||||||
resetPosition();
|
resetPosition();
|
||||||
if (mob.dialog != null && mob.dialog.canShow()) { //This enemy has something to say. Display a dialog like if it was a DialogActor but only if dialogue is possible.
|
if (mob.dialog != null && mob.dialog.canShow()) { //This enemy has something to say. Display a dialog like if it was a DialogActor but only if dialogue is possible.
|
||||||
mob.dialog.activate();
|
mob.dialog.activate();
|
||||||
@@ -1032,7 +1026,9 @@ public class MapStage extends GameStage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showDialog() {
|
public void showDialog() {
|
||||||
|
if (dialogStage == null){
|
||||||
|
setDialogStage(GameHUD.getInstance());
|
||||||
|
}
|
||||||
dialogButtonMap.clear();
|
dialogButtonMap.clear();
|
||||||
for (int i = 0; i < dialog.getButtonTable().getCells().size; i++) {
|
for (int i = 0; i < dialog.getButtonTable().getCells().size; i++) {
|
||||||
dialogButtonMap.add((TextraButton) dialog.getButtonTable().getCells().get(i).getActor());
|
dialogButtonMap.add((TextraButton) dialog.getButtonTable().getCells().get(i).getActor());
|
||||||
@@ -1048,6 +1044,7 @@ public class MapStage extends GameStage {
|
|||||||
dialog.hide(Actions.sequence(Actions.sizeTo(dialog.getOriginX(), dialog.getOriginY(), 0.3f), Actions.hide()));
|
dialog.hide(Actions.sequence(Actions.sizeTo(dialog.getOriginX(), dialog.getOriginY(), 0.3f), Actions.hide()));
|
||||||
dialogOnlyInput = false;
|
dialogOnlyInput = false;
|
||||||
selectedKey = null;
|
selectedKey = null;
|
||||||
|
dialog.clearListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDialogStage(Stage dialogStage) {
|
public void setDialogStage(Stage dialogStage) {
|
||||||
@@ -1061,6 +1058,9 @@ public class MapStage extends GameStage {
|
|||||||
|
|
||||||
public void setQuestFlag(String key, int value) {
|
public void setQuestFlag(String key, int value) {
|
||||||
changes.getMapFlags().put(key, (byte) value);
|
changes.getMapFlags().put(key, (byte) value);
|
||||||
|
|
||||||
|
AdventureQuestController.instance().updateQuestsMapFlag(key,value);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void advanceQuestFlag(String key) {
|
public void advanceQuestFlag(String key) {
|
||||||
@@ -1070,6 +1070,9 @@ public class MapStage extends GameStage {
|
|||||||
} else {
|
} else {
|
||||||
C.put(key, (byte) 1);
|
C.put(key, (byte) 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AdventureQuestController.instance().updateQuestsMapFlag(key,changes.getMapFlags().get(key));
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkQuestFlag(String key) {
|
public boolean checkQuestFlag(String key) {
|
||||||
|
|||||||
@@ -48,7 +48,8 @@ public class PointOfInterestMapSprite extends MapSprite {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Batch batch, float parentAlpha) {
|
public void draw(Batch batch, float parentAlpha) {
|
||||||
super.draw(batch, parentAlpha);
|
if (pointOfInterest.getActive())
|
||||||
|
super.draw(batch, parentAlpha);
|
||||||
//batch.draw(getDebugTexture(),getX(),getY());
|
//batch.draw(getDebugTexture(),getX(),getY());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class WorldBackground extends Actor {
|
|||||||
if (chunksSpritesBackground[x][y] == null)
|
if (chunksSpritesBackground[x][y] == null)
|
||||||
chunksSpritesBackground[x][y] = MapSprite.getMapSprites(x, y, MapSprite.BackgroundLayer);
|
chunksSpritesBackground[x][y] = MapSprite.getMapSprites(x, y, MapSprite.BackgroundLayer);
|
||||||
for (Actor sprite : chunksSpritesBackground[x][y]) {
|
for (Actor sprite : chunksSpritesBackground[x][y]) {
|
||||||
stage.getBackgroundSprites().addActor(sprite);
|
stage.getBackgroundSprites().addActor(sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.badlogic.gdx.utils.viewport.Viewport;
|
|||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.adventure.character.CharacterSprite;
|
import forge.adventure.character.CharacterSprite;
|
||||||
import forge.adventure.character.EnemySprite;
|
import forge.adventure.character.EnemySprite;
|
||||||
|
import forge.adventure.data.AdventureQuestData;
|
||||||
import forge.adventure.data.BiomeData;
|
import forge.adventure.data.BiomeData;
|
||||||
import forge.adventure.data.EnemyData;
|
import forge.adventure.data.EnemyData;
|
||||||
import forge.adventure.data.WorldData;
|
import forge.adventure.data.WorldData;
|
||||||
@@ -18,10 +19,7 @@ import forge.adventure.scene.DuelScene;
|
|||||||
import forge.adventure.scene.RewardScene;
|
import forge.adventure.scene.RewardScene;
|
||||||
import forge.adventure.scene.Scene;
|
import forge.adventure.scene.Scene;
|
||||||
import forge.adventure.scene.TileMapScene;
|
import forge.adventure.scene.TileMapScene;
|
||||||
import forge.adventure.util.Current;
|
import forge.adventure.util.*;
|
||||||
import forge.adventure.util.Paths;
|
|
||||||
import forge.adventure.util.SaveFileContent;
|
|
||||||
import forge.adventure.util.SaveFileData;
|
|
||||||
import forge.adventure.world.World;
|
import forge.adventure.world.World;
|
||||||
import forge.adventure.world.WorldSave;
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.gui.FThreads;
|
import forge.gui.FThreads;
|
||||||
@@ -52,11 +50,15 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
private final static Float dieTimer = 20f;//todo config
|
private final static Float dieTimer = 20f;//todo config
|
||||||
private Float globalTimer = 0f;
|
private Float globalTimer = 0f;
|
||||||
|
|
||||||
|
NavArrowActor navArrow;
|
||||||
public WorldStage() {
|
public WorldStage() {
|
||||||
super();
|
super();
|
||||||
background = new WorldBackground(this);
|
background = new WorldBackground(this);
|
||||||
addActor(background);
|
addActor(background);
|
||||||
background.setZIndex(0);
|
background.setZIndex(0);
|
||||||
|
navArrow = new NavArrowActor();
|
||||||
|
addActor(navArrow);
|
||||||
|
navArrow.setZIndex(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WorldStage getInstance() {
|
public static WorldStage getInstance() {
|
||||||
@@ -68,6 +70,9 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActing(float delta) {
|
protected void onActing(float delta) {
|
||||||
|
if (isPaused() || MapStage.getInstance().isDialogOnlyInput())
|
||||||
|
return;
|
||||||
|
drawNavigationArrow();
|
||||||
if (player.isMoving()) {
|
if (player.isMoving()) {
|
||||||
handleMonsterSpawn(delta);
|
handleMonsterSpawn(delta);
|
||||||
handlePointsOfInterestCollision();
|
handlePointsOfInterestCollision();
|
||||||
@@ -75,8 +80,9 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
Iterator<Pair<Float, EnemySprite>> it = enemies.iterator();
|
Iterator<Pair<Float, EnemySprite>> it = enemies.iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
Pair<Float, EnemySprite> pair = it.next();
|
Pair<Float, EnemySprite> pair = it.next();
|
||||||
if (globalTimer >= pair.getKey() + dieTimer) {
|
if (globalTimer >= pair.getKey() + pair.getValue().getLifetime()) {
|
||||||
|
AdventureQuestController.instance().updateDespawn(pair.getValue());
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
||||||
foregroundSprites.removeActor(pair.getValue());
|
foregroundSprites.removeActor(pair.getValue());
|
||||||
it.remove();
|
it.remove();
|
||||||
continue;
|
continue;
|
||||||
@@ -166,8 +172,10 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
startPause(0.3f, () -> {
|
startPause(0.3f, () -> {
|
||||||
RewardScene.instance().loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null);
|
RewardScene.instance().loadRewards(currentMob.getRewards(), RewardScene.Type.Loot, null);
|
||||||
WorldStage.this.removeEnemy(currentMob);
|
WorldStage.this.removeEnemy(currentMob);
|
||||||
currentMob = null;
|
AdventureQuestController.instance().updateQuestsWin(currentMob);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
||||||
Forge.switchScene(RewardScene.instance());
|
Forge.switchScene(RewardScene.instance());
|
||||||
|
currentMob = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 1f);
|
}, 1f);
|
||||||
@@ -178,6 +186,8 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
startPause(0.5f, () -> {
|
startPause(0.5f, () -> {
|
||||||
currentMob.resetCollisionHeight();
|
currentMob.resetCollisionHeight();
|
||||||
Current.player().defeated();
|
Current.player().defeated();
|
||||||
|
AdventureQuestController.instance().updateQuestsLose(currentMob);
|
||||||
|
AdventureQuestController.instance().showQuestDialogs(MapStage.getInstance());
|
||||||
WorldStage.this.removeEnemy(currentMob);
|
WorldStage.this.removeEnemy(currentMob);
|
||||||
currentMob = null;
|
currentMob = null;
|
||||||
});
|
});
|
||||||
@@ -188,6 +198,10 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
for (Actor actor : foregroundSprites.getChildren()) {
|
for (Actor actor : foregroundSprites.getChildren()) {
|
||||||
if (actor.getClass() == PointOfInterestMapSprite.class) {
|
if (actor.getClass() == PointOfInterestMapSprite.class) {
|
||||||
PointOfInterestMapSprite point = (PointOfInterestMapSprite) actor;
|
PointOfInterestMapSprite point = (PointOfInterestMapSprite) actor;
|
||||||
|
if (!point.getPointOfInterest().getActive())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (player.collideWith(point.getBoundingRect())) {
|
if (player.collideWith(point.getBoundingRect())) {
|
||||||
if (point == collidingPoint) {
|
if (point == collidingPoint) {
|
||||||
continue;
|
continue;
|
||||||
@@ -222,6 +236,16 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleMonsterSpawn(float delta) {
|
private void handleMonsterSpawn(float delta) {
|
||||||
|
for (Actor sprite : foregroundSprites.getChildren()) {
|
||||||
|
if (AdventureQuestController.instance().getQuestSprites().remove(sprite)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (EnemySprite questSprite : AdventureQuestController.instance().getQuestSprites()) {
|
||||||
|
if (!foregroundSprites.getChildren().contains(questSprite, true)) {
|
||||||
|
spawnQuestSprite(questSprite,2.5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
World world = WorldSave.getCurrentSave().getWorld();
|
World world = WorldSave.getCurrentSave().getWorld();
|
||||||
int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize()));
|
int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize()));
|
||||||
List<BiomeData> biomeData = WorldSave.getCurrentSave().getWorld().getData().GetBiomes();
|
List<BiomeData> biomeData = WorldSave.getCurrentSave().getWorld().getData().GetBiomes();
|
||||||
@@ -245,10 +269,9 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
spawn(enemyData);
|
spawn(enemyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean spawn(EnemyData enemyData) {
|
private boolean spawn(EnemySprite sprite){
|
||||||
if (enemyData == null)
|
if (sprite == null)
|
||||||
return false;
|
return false;
|
||||||
EnemySprite sprite = new EnemySprite(enemyData);
|
|
||||||
float unit = Scene.getIntendedHeight() / 6f;
|
float unit = Scene.getIntendedHeight() / 6f;
|
||||||
Vector2 spawnPos = new Vector2(1, 1);
|
Vector2 spawnPos = new Vector2(1, 1);
|
||||||
for (int j = 0; j < 10; j++) {
|
for (int j = 0; j < 10; j++) {
|
||||||
@@ -264,7 +287,37 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
foregroundSprites.addActor(sprite);
|
foregroundSprites.addActor(sprite);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int g = 0;
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean spawn(EnemyData enemyData) {
|
||||||
|
if (enemyData == null)
|
||||||
|
return false;
|
||||||
|
EnemySprite sprite = new EnemySprite(enemyData);
|
||||||
|
return spawn(sprite);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean spawnQuestSprite(EnemySprite sprite, float distanceMultiplier){
|
||||||
|
if (sprite == null)
|
||||||
|
return false;
|
||||||
|
float unit = Scene.getIntendedHeight() / 6f;
|
||||||
|
Vector2 spawnPos = new Vector2(1, 1);
|
||||||
|
for (int j = 0; j < 10; j++) {
|
||||||
|
spawnPos.setLength((unit + (unit * 3) * rand.nextFloat()) * distanceMultiplier);
|
||||||
|
spawnPos.setAngleDeg(360 * rand.nextFloat());
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
boolean enemyXIsBigger = sprite.getX() > player.getX();
|
||||||
|
boolean enemyYIsBigger = sprite.getY() > player.getY();
|
||||||
|
sprite.setX(player.getX() + spawnPos.x + (i * sprite.getWidth() * (enemyXIsBigger ? 1 : -1)));//maybe find a better way to get spawn points
|
||||||
|
sprite.setY(player.getY() + spawnPos.y + (i * sprite.getHeight() * (enemyYIsBigger ? 1 : -1)));
|
||||||
|
if (sprite.getData().flying || !WorldSave.getCurrentSave().getWorld().collidingTile(sprite.boundingRect())) {
|
||||||
|
enemies.add(Pair.of(globalTimer, sprite));
|
||||||
|
foregroundSprites.addActor(sprite);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -382,4 +435,38 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
|||||||
player.playEffect(Paths.TRIGGER_KILL);
|
player.playEffect(Paths.TRIGGER_KILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void drawNavigationArrow(){
|
||||||
|
Vector2 navDirection = null;
|
||||||
|
for (AdventureQuestData adq: Current.player().getQuests())
|
||||||
|
{
|
||||||
|
if (adq.isTracked) {
|
||||||
|
if (adq.getTargetPOI() != null) {
|
||||||
|
navDirection = adq.getTargetPOI().getNavigationVector(player.pos());
|
||||||
|
|
||||||
|
} else if (adq.getTargetEnemySprite() != null) {
|
||||||
|
EnemySprite target = adq.getTargetEnemySprite();
|
||||||
|
for (Pair<Float, EnemySprite> active :enemies)
|
||||||
|
{
|
||||||
|
EnemySprite sprite = active.getValue();
|
||||||
|
if (sprite.equals(target)){
|
||||||
|
navDirection = new Vector2(adq.getTargetEnemySprite().pos()).sub(player.getX(), player.getY());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (navDirection != null)
|
||||||
|
{
|
||||||
|
navArrow.navTargetAngle = navDirection.angleDeg();
|
||||||
|
navArrow.setVisible(true);
|
||||||
|
navArrow.setPosition(getPlayerSprite().getX() + (getPlayerSprite().getWidth()/2), getPlayerSprite().getY() + (getPlayerSprite().getHeight()/2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
navArrow.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,347 @@
|
|||||||
|
package forge.adventure.util;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.Json;
|
||||||
|
import forge.adventure.character.EnemySprite;
|
||||||
|
import forge.adventure.data.*;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterest;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterestChanges;
|
||||||
|
import forge.adventure.stage.GameStage;
|
||||||
|
import forge.adventure.stage.MapStage;
|
||||||
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AdventureQuestController implements Serializable {
|
||||||
|
|
||||||
|
public enum ObjectiveTypes{
|
||||||
|
None,
|
||||||
|
Arena,
|
||||||
|
Clear,
|
||||||
|
Defeat,
|
||||||
|
Delivery,
|
||||||
|
Escort,
|
||||||
|
Fetch,
|
||||||
|
Find,
|
||||||
|
Gather,
|
||||||
|
Give,
|
||||||
|
Hunt,
|
||||||
|
MapFlag,
|
||||||
|
Leave,
|
||||||
|
Patrol,
|
||||||
|
QuestFlag,
|
||||||
|
Rescue,
|
||||||
|
Siege,
|
||||||
|
Travel,
|
||||||
|
Use
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum QuestStatus{
|
||||||
|
None,
|
||||||
|
Inactive,
|
||||||
|
Active,
|
||||||
|
Complete,
|
||||||
|
Failed
|
||||||
|
}
|
||||||
|
private Map<String, Long> nextQuestDate = new HashMap<>();
|
||||||
|
private int maximumSideQuests = 5; //todo: move to configuration file
|
||||||
|
private transient boolean inDialog = false;
|
||||||
|
private transient Array<AdventureQuestData> allQuests = new Array<>();
|
||||||
|
private transient Array<AdventureQuestData> allSideQuests = new Array<>();
|
||||||
|
private Queue<DialogData> dialogQueue = new LinkedList<>();
|
||||||
|
private Map<String,Date> questAvailability = new HashMap<>();
|
||||||
|
public PointOfInterest mostRecentPOI;
|
||||||
|
private List<EnemySprite> enemySpriteList= new ArrayList<>();
|
||||||
|
public void showQuestDialogs(GameStage stage) {
|
||||||
|
List<AdventureQuestData> finishedQuests = new ArrayList<>();
|
||||||
|
|
||||||
|
if (stage instanceof MapStage){
|
||||||
|
for (AdventureQuestData quest : Current.player().getQuests()) {
|
||||||
|
DialogData prologue = quest.getPrologue();
|
||||||
|
if (prologue != null && (!prologue.text.isEmpty()) ){
|
||||||
|
dialogQueue.add(prologue);
|
||||||
|
}
|
||||||
|
for (AdventureQuestStage questStage : quest.stages)
|
||||||
|
{
|
||||||
|
if (questStage.prologue != null && (!questStage.prologue.text.isEmpty()) && !questStage.prologueDisplayed){
|
||||||
|
questStage.prologueDisplayed = true;
|
||||||
|
dialogQueue.add(questStage.prologue);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questStage.getStatus() == QuestStatus.Failed && questStage.failureDialog != null && !questStage.failureDialog.text.isEmpty()){
|
||||||
|
dialogQueue.add(questStage.failureDialog);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questStage.getStatus() == QuestStatus.Complete && questStage.epilogue != null && (!questStage.epilogue.text.isEmpty()) && !questStage.epilogueDisplayed){
|
||||||
|
questStage.epilogueDisplayed = true;
|
||||||
|
dialogQueue.add(questStage.epilogue);
|
||||||
|
}
|
||||||
|
// if (questStage.getStatus() != QuestStatus.Complete){
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quest.failed){
|
||||||
|
finishedQuests.add(quest);
|
||||||
|
if (quest.failureDialog != null && !quest.failureDialog.text.isEmpty()){
|
||||||
|
dialogQueue.add(quest.failureDialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!quest.completed)
|
||||||
|
continue;
|
||||||
|
DialogData epilogue = quest.getEpilogue();
|
||||||
|
if (epilogue != null && (!epilogue.text.isEmpty())){
|
||||||
|
dialogQueue.add(epilogue);
|
||||||
|
|
||||||
|
}
|
||||||
|
finishedQuests.add(quest);
|
||||||
|
}
|
||||||
|
if (!inDialog){
|
||||||
|
inDialog = true;
|
||||||
|
displayNextDialog((MapStage) stage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (AdventureQuestData toRemove : finishedQuests) {
|
||||||
|
|
||||||
|
if (!toRemove.failed && locationHasMoreQuests()){
|
||||||
|
nextQuestDate.remove(toRemove.sourceID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Current.player().removeQuest(toRemove);
|
||||||
|
//Todo: Add quest to a separate "completed / failed" log?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean locationHasMoreQuests(){
|
||||||
|
//intent: eventually stop providing quests for the day in a given town to encourage exploration
|
||||||
|
//todo: make values configurable
|
||||||
|
return new Random().nextFloat() <= 0.85f;
|
||||||
|
}
|
||||||
|
public void displayNextDialog(MapStage stage){
|
||||||
|
if (dialogQueue.peek() == null)
|
||||||
|
{
|
||||||
|
inDialog = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MapDialog dialog = new MapDialog(dialogQueue.remove(), stage, -1);
|
||||||
|
stage.showDialog();
|
||||||
|
dialog.activate();
|
||||||
|
dialog.addDialogCompleteListener(e -> displayNextDialog(stage));
|
||||||
|
|
||||||
|
}
|
||||||
|
public static class DistanceSort implements Comparator<PointOfInterest>
|
||||||
|
{
|
||||||
|
//ToDo: Make this more generic, compare PoI, mobs, random points, and player position
|
||||||
|
// In process, perhaps adjust nav indicator based on distance to target
|
||||||
|
//Sorts POI by distance from the player
|
||||||
|
public int compare(PointOfInterest a, PointOfInterest b)
|
||||||
|
{
|
||||||
|
float distToA = new Vector2(a.getPosition()).sub(Current.player().getWorldPosX(), Current.player().getWorldPosY()).len();
|
||||||
|
float distToB = new Vector2(b.getPosition()).sub(Current.player().getWorldPosX(), Current.player().getWorldPosY()).len();
|
||||||
|
if (distToA - distToB < 0.0f)
|
||||||
|
return -1;
|
||||||
|
else if (distToA - distToB > 0.0f)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static AdventureQuestController object;
|
||||||
|
|
||||||
|
public static AdventureQuestController instance() {
|
||||||
|
if (object == null) {
|
||||||
|
object = new AdventureQuestController();
|
||||||
|
object.loadData();
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AdventureQuestController(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestController(AdventureQuestController other){
|
||||||
|
if (object == null) {
|
||||||
|
maximumSideQuests = other.maximumSideQuests;
|
||||||
|
mostRecentPOI = other.mostRecentPOI;
|
||||||
|
dialogQueue = other.dialogQueue;
|
||||||
|
questAvailability = other.questAvailability;
|
||||||
|
|
||||||
|
object = this;
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
System.out.println("Could not initialize AdventureQuestController. An instance already exists and cannot be merged.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadData(){
|
||||||
|
Json json = new Json();
|
||||||
|
FileHandle handle = Config.instance().getFile(Paths.QUESTS);
|
||||||
|
if (handle.exists())
|
||||||
|
{
|
||||||
|
allQuests =json.fromJson(Array.class, AdventureQuestData.class, handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AdventureQuestData q : allQuests){
|
||||||
|
if (q.storyQuest) continue;
|
||||||
|
allSideQuests.add(q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateEnteredPOI(PointOfInterest arrivedAt)
|
||||||
|
{
|
||||||
|
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
|
||||||
|
currentQuest.updateEnteredPOI(arrivedAt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateQuestsMapFlag(String updatedMapFlag, int updatedFlagValue)
|
||||||
|
{
|
||||||
|
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
|
||||||
|
currentQuest.updateMapFlag(updatedMapFlag, updatedFlagValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateQuestsLeave(){
|
||||||
|
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
|
||||||
|
currentQuest.updateLeave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateQuestsWin(EnemySprite defeated, ArrayList<EnemySprite> enemies){
|
||||||
|
boolean allEnemiesCleared = true;
|
||||||
|
if (enemies != null) {
|
||||||
|
//battle was won in a dungeon, check for "clear" objectives
|
||||||
|
for (EnemySprite enemy : enemies) {
|
||||||
|
if (enemy.getStage() != null && !enemy.equals(defeated)) {
|
||||||
|
//actor is an enemy that is present on the map. Check to see if there's a valid reason.
|
||||||
|
if (enemy.defeatDialog != null) {
|
||||||
|
//This enemy cannot be removed from the map by defeating it, ignore it for "cleared" purposes
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allEnemiesCleared = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
|
||||||
|
currentQuest.updateWin(defeated, allEnemiesCleared);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void updateQuestsWin(EnemySprite defeated){
|
||||||
|
updateQuestsWin(defeated, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateQuestsLose(EnemySprite defeatedBy){
|
||||||
|
for(AdventureQuestData currentQuest : Current.player().getQuests()) {
|
||||||
|
currentQuest.updateLose(defeatedBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDespawn(EnemySprite despawned){
|
||||||
|
for(AdventureQuestData currentQuest: Current.player().getQuests()) {
|
||||||
|
currentQuest.updateDespawn(despawned);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestData generateQuest(int id){
|
||||||
|
AdventureQuestData generated = null;
|
||||||
|
for (AdventureQuestData template: allQuests) {
|
||||||
|
if (template.isTemplate && template.getID() == id){
|
||||||
|
generated = new AdventureQuestData(template);
|
||||||
|
generated.initialize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return generated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addQuestSprites(AdventureQuestStage stage){
|
||||||
|
if (stage.getTargetSprite() != null){
|
||||||
|
enemySpriteList.add(stage.getTargetSprite());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<EnemySprite> getQuestSprites(){
|
||||||
|
return enemySpriteList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String randomItemName()
|
||||||
|
{ //todo: expand and include in fetch/delivery quests
|
||||||
|
String[] options = {"collection of frequently asked questions","case of card sleeves", "well loved playmat", "copy of Richard Garfield's autobiography", "collection of random foreign language cards", "lucky coin", "giant card binder", "unsorted box of commons", "bucket full of pieces of shattered artifacts","depleted mana shard"};
|
||||||
|
|
||||||
|
return Aggregates.random(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void abandon(AdventureQuestData quest){
|
||||||
|
quest.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdventureQuestData getQuestNPCResponse(String pointID, PointOfInterestChanges changes, String questOrigin) {
|
||||||
|
AdventureQuestData ret;
|
||||||
|
|
||||||
|
for (AdventureQuestData q : Current.player().getQuests()) {
|
||||||
|
if (q.completed || q.storyQuest)
|
||||||
|
continue;
|
||||||
|
if (q.sourceID.equals(pointID)) {
|
||||||
|
//remind player about current active side quest
|
||||||
|
DialogData response = new DialogData();
|
||||||
|
response.text = "\"You haven't finished the last thing we asked you to do!\" (" + q.name +") ";
|
||||||
|
DialogData dismiss = new DialogData();
|
||||||
|
dismiss.name = "\"Oh, right, let me go take care of that.\"";
|
||||||
|
response.options = new DialogData[]{dismiss};
|
||||||
|
ret = new AdventureQuestData();
|
||||||
|
ret.offerDialog = response;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nextQuestDate.containsKey(pointID) && nextQuestDate.get(pointID) >= LocalDate.now().toEpochDay()){
|
||||||
|
//No more side quests available here today due to previous activity
|
||||||
|
DialogData response = new DialogData();
|
||||||
|
response.text = "\"We don't have anything new for you to do right now. Come back tomorrow.\"";
|
||||||
|
DialogData dismiss = new DialogData();
|
||||||
|
dismiss.name = "\"Okay.\" (Leave)";
|
||||||
|
response.options = new DialogData[]{dismiss};
|
||||||
|
ret = new AdventureQuestData();
|
||||||
|
ret.offerDialog = response;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tooManyQuests(Current.player().getQuests())) {
|
||||||
|
//No more side quests available here today, too many active
|
||||||
|
DialogData response = new DialogData();
|
||||||
|
response.text = "\"Adventurer, we need your assistance!\"";
|
||||||
|
DialogData dismiss = new DialogData();
|
||||||
|
dismiss.name = "\"I can't, I have far too many things to do right now\" (Your quest log is too full already) (Leave)";
|
||||||
|
response.options = new DialogData[]{dismiss};
|
||||||
|
ret = new AdventureQuestData();
|
||||||
|
ret.offerDialog = response;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
//todo - Make use of questOrigin in selecting appropriate quests
|
||||||
|
nextQuestDate.put(pointID, LocalDate.now().toEpochDay());
|
||||||
|
ret = new AdventureQuestData(Aggregates.random(allSideQuests));
|
||||||
|
ret.sourceID = pointID;
|
||||||
|
ret.initialize();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean tooManyQuests(List<AdventureQuestData> existing){
|
||||||
|
int sideQuests = 0;
|
||||||
|
|
||||||
|
for (AdventureQuestData quest : existing){
|
||||||
|
if (quest.storyQuest || quest.completed || quest.failed)
|
||||||
|
continue;
|
||||||
|
sideQuests++;
|
||||||
|
}
|
||||||
|
return (sideQuests >= maximumSideQuests);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import forge.StaticData;
|
|||||||
import forge.adventure.data.GeneratedDeckData;
|
import forge.adventure.data.GeneratedDeckData;
|
||||||
import forge.adventure.data.GeneratedDeckTemplateData;
|
import forge.adventure.data.GeneratedDeckTemplateData;
|
||||||
import forge.adventure.data.RewardData;
|
import forge.adventure.data.RewardData;
|
||||||
import forge.adventure.world.WorldSave;
|
|
||||||
import forge.card.*;
|
import forge.card.*;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
@@ -298,13 +297,14 @@ public class CardUtil {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<PaperCard> generateCards(Iterable<PaperCard> cards,final RewardData data, final int count)
|
public static List<PaperCard> generateCards(Iterable<PaperCard> cards,final RewardData data, final int count, Random r)
|
||||||
{
|
{
|
||||||
|
|
||||||
final List<PaperCard> result = new ArrayList<>();
|
final List<PaperCard> result = new ArrayList<>();
|
||||||
List<PaperCard> pool = getPredicateResult(cards, data);
|
List<PaperCard> pool = getPredicateResult(cards, data);
|
||||||
if (pool.size() > 0) {
|
if (pool.size() > 0) {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
PaperCard candidate = pool.get(WorldSave.getCurrentSave().getWorld().getRandom().nextInt(pool.size()));
|
PaperCard candidate = pool.get(r.nextInt(pool.size()));
|
||||||
if (candidate != null) {
|
if (candidate != null) {
|
||||||
result.add(candidate);
|
result.add(candidate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ public class Config {
|
|||||||
if(settingsData.cardTooltipAdjLandscape == null || settingsData.cardTooltipAdjLandscape == 0f)
|
if(settingsData.cardTooltipAdjLandscape == null || settingsData.cardTooltipAdjLandscape == 0f)
|
||||||
settingsData.cardTooltipAdjLandscape=1f;
|
settingsData.cardTooltipAdjLandscape=1f;
|
||||||
|
|
||||||
|
|
||||||
|
//prefix = "forge-gui/res/adventure/Shandalar/";
|
||||||
prefix = getPlanePath(settingsData.plane);
|
prefix = getPlanePath(settingsData.plane);
|
||||||
|
|
||||||
currentConfig = this;
|
currentConfig = this;
|
||||||
@@ -115,7 +117,7 @@ public class Config {
|
|||||||
|
|
||||||
private String resPath() {
|
private String resPath() {
|
||||||
|
|
||||||
return GuiBase.isAndroid() ? ForgeConstants.ASSETS_DIR : Files.exists(Paths.get("./res"))?"./":"../forge-gui/";
|
return GuiBase.isAndroid() ? ForgeConstants.ASSETS_DIR : Files.exists(Paths.get("./res"))?"./":Files.exists(Paths.get("./forge-gui/"))?"./forge-gui/":"../forge-gui";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlanePath(String plane) {
|
public String getPlanePath(String plane) {
|
||||||
|
|||||||
@@ -14,15 +14,23 @@ import com.github.tommyettinger.textra.TypingLabel;
|
|||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.adventure.character.EnemySprite;
|
import forge.adventure.character.EnemySprite;
|
||||||
import forge.adventure.data.DialogData;
|
import forge.adventure.data.DialogData;
|
||||||
|
import forge.adventure.data.RewardData;
|
||||||
import forge.adventure.player.AdventurePlayer;
|
import forge.adventure.player.AdventurePlayer;
|
||||||
|
import forge.adventure.pointofintrest.PointOfInterestChanges;
|
||||||
import forge.adventure.stage.GameHUD;
|
import forge.adventure.stage.GameHUD;
|
||||||
|
import forge.adventure.scene.RewardScene;
|
||||||
import forge.adventure.stage.MapStage;
|
import forge.adventure.stage.MapStage;
|
||||||
|
import forge.adventure.world.WorldSave;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.localinstance.properties.ForgePreferences;
|
import forge.localinstance.properties.ForgePreferences;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.EventListenerList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MapDialog
|
* MapDialog
|
||||||
* Implements a dialogue/event tree for dialogs.
|
* Implements a dialogue/event tree for dialogs.
|
||||||
@@ -35,7 +43,7 @@ public class MapDialog {
|
|||||||
private final static float WIDTH = 250f;
|
private final static float WIDTH = 250f;
|
||||||
static private final String defaultJSON = "[\n" +
|
static private final String defaultJSON = "[\n" +
|
||||||
" {\n" +
|
" {\n" +
|
||||||
" \"effect\":[],\n" +
|
//" \"effect\":[],\n" +
|
||||||
" \"name\":\"Error\",\n" +
|
" \"name\":\"Error\",\n" +
|
||||||
" \"text\":\"This is a fallback dialog.\\nPlease check Forge logs for errors.\",\n" +
|
" \"text\":\"This is a fallback dialog.\\nPlease check Forge logs for errors.\",\n" +
|
||||||
" \"condition\":[],\n" +
|
" \"condition\":[],\n" +
|
||||||
@@ -50,7 +58,6 @@ public class MapDialog {
|
|||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
this.parentID = parentID;
|
this.parentID = parentID;
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (S.isEmpty()) {
|
if (S.isEmpty()) {
|
||||||
System.err.print("Dialog error. Dialog property is empty.\n");
|
System.err.print("Dialog error. Dialog property is empty.\n");
|
||||||
this.data = JSONStringLoader.parse(Array.class, DialogData.class, defaultJSON, defaultJSON);
|
this.data = JSONStringLoader.parse(Array.class, DialogData.class, defaultJSON, defaultJSON);
|
||||||
@@ -63,6 +70,25 @@ public class MapDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MapDialog(DialogData prebuiltDialog, MapStage stage, int parentID) {
|
||||||
|
this.stage = stage;
|
||||||
|
this.parentID = parentID;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (prebuiltDialog == null) {
|
||||||
|
System.err.print("Dialog error. Dialog provided is null.\n");
|
||||||
|
this.data = JSONStringLoader.parse(Array.class, DialogData.class, defaultJSON, defaultJSON);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.data = new Array<>();
|
||||||
|
this.data.add(prebuiltDialog);
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Pair<FileHandle, Music> audio = null;
|
Pair<FileHandle, Music> audio = null;
|
||||||
|
|
||||||
void unload() {
|
void unload() {
|
||||||
@@ -174,8 +200,10 @@ public class MapDialog {
|
|||||||
super.clicked(event, x, y);
|
super.clicked(event, x, y);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (i == 0)
|
if (i == 0) {
|
||||||
stage.hideDialog();
|
stage.hideDialog();
|
||||||
|
emitDialogFinished();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
stage.showDialog();
|
stage.showDialog();
|
||||||
} else {
|
} else {
|
||||||
@@ -183,6 +211,35 @@ public class MapDialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected EventListenerList dialogCompleteList = new EventListenerList();
|
||||||
|
protected EventListenerList questAcceptedList = new EventListenerList();
|
||||||
|
public void addDialogCompleteListener(ChangeListener listener) {
|
||||||
|
dialogCompleteList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
public void addQuestAcceptedListener(ChangeListener listener){
|
||||||
|
questAcceptedList.add(ChangeListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitDialogFinished(){
|
||||||
|
ChangeListener[] listeners = dialogCompleteList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void emitQuestAccepted(){
|
||||||
|
ChangeListener[] listeners = questAcceptedList.getListeners(ChangeListener.class);
|
||||||
|
if (listeners != null && listeners.length > 0) {
|
||||||
|
ChangeEvent evt = new ChangeEvent(this);
|
||||||
|
for (ChangeListener listener : listeners) {
|
||||||
|
listener.stateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void fadeIn() {
|
void fadeIn() {
|
||||||
disposeAudio(true);
|
disposeAudio(true);
|
||||||
GameHUD.getInstance().fadeIn();
|
GameHUD.getInstance().fadeIn();
|
||||||
@@ -203,10 +260,13 @@ public class MapDialog {
|
|||||||
void setEffects(DialogData.ActionData[] data) {
|
void setEffects(DialogData.ActionData[] data) {
|
||||||
if (data == null) return;
|
if (data == null) return;
|
||||||
for (DialogData.ActionData E : data) {
|
for (DialogData.ActionData E : data) {
|
||||||
if (E.removeItem != null) { //Removes an item from the player's inventory.
|
if (E == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (E.removeItem != null&& (!E.removeItem.isEmpty())) { //Removes an item from the player's inventory.
|
||||||
Current.player().removeItem(E.removeItem);
|
Current.player().removeItem(E.removeItem);
|
||||||
}
|
}
|
||||||
if (E.addItem != null) { //Gives an item to the player.
|
if (E.addItem != null&& (!E.addItem.isEmpty())) { //Gives an item to the player.
|
||||||
Current.player().addItem(E.addItem);
|
Current.player().addItem(E.addItem);
|
||||||
}
|
}
|
||||||
if (E.addLife != 0) { //Gives (positive or negative) life to the player. Cannot go over max health.
|
if (E.addLife != 0) { //Gives (positive or negative) life to the player. Cannot go over max health.
|
||||||
@@ -216,6 +276,15 @@ public class MapDialog {
|
|||||||
if (E.addGold > 0) Current.player().giveGold(E.addGold);
|
if (E.addGold > 0) Current.player().giveGold(E.addGold);
|
||||||
else Current.player().takeGold(-E.addGold);
|
else Current.player().takeGold(-E.addGold);
|
||||||
}
|
}
|
||||||
|
if (E.addMapReputation != 0) {
|
||||||
|
PointOfInterestChanges p;
|
||||||
|
if (E.POIReference.length()>0 && !E.POIReference.contains("$"))
|
||||||
|
p = WorldSave.getCurrentSave().getPointOfInterestChanges( E.POIReference);
|
||||||
|
else
|
||||||
|
p = stage.getChanges();
|
||||||
|
if (p != null)
|
||||||
|
p.addMapReputation(E.addMapReputation);
|
||||||
|
}
|
||||||
if (E.deleteMapObject != 0) { //Removes a dummy object from the map.
|
if (E.deleteMapObject != 0) { //Removes a dummy object from the map.
|
||||||
if (E.deleteMapObject < 0) stage.deleteObject(parentID);
|
if (E.deleteMapObject < 0) stage.deleteObject(parentID);
|
||||||
else stage.deleteObject(E.deleteMapObject);
|
else stage.deleteObject(E.deleteMapObject);
|
||||||
@@ -246,6 +315,17 @@ public class MapDialog {
|
|||||||
EnemySprite EN = stage.getEnemyByID(parentID);
|
EnemySprite EN = stage.getEnemyByID(parentID);
|
||||||
EN.effect = E.setEffect;
|
EN.effect = E.setEffect;
|
||||||
}
|
}
|
||||||
|
if (E.grantRewards != null && E.grantRewards.length > 0) {
|
||||||
|
Array<Reward> ret = new Array<Reward>();
|
||||||
|
for(RewardData rdata:E.grantRewards) {
|
||||||
|
ret.addAll(rdata.generate(false, true));
|
||||||
|
}
|
||||||
|
RewardScene.instance().loadRewards(ret, RewardScene.Type.QuestReward, null);
|
||||||
|
Forge.switchScene(RewardScene.instance());
|
||||||
|
}
|
||||||
|
if (E.issueQuest != null && (!E.issueQuest.isEmpty())) {
|
||||||
|
emitQuestAccepted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,10 +364,15 @@ public class MapDialog {
|
|||||||
if (!condition.not) return false;
|
if (!condition.not) return false;
|
||||||
} else if (condition.not) return false;
|
} else if (condition.not) return false;
|
||||||
}
|
}
|
||||||
if (condition.hasBlessing != null && !condition.hasBlessing.isEmpty()) { //Check for a named blessing.
|
if (condition.hasMapReputation != Integer.MIN_VALUE){ //Check for at least X reputation.
|
||||||
if (!player.hasBlessing(condition.hasBlessing)) {
|
if ( stage.getChanges().getMapReputation() < condition.hasMapReputation + 1) {
|
||||||
if (!condition.not) return false;
|
if (!condition.not) return false;
|
||||||
} else if (condition.not) return false;
|
} else if(condition.not) return false;
|
||||||
|
}
|
||||||
|
if (condition.hasBlessing != null && !condition.hasBlessing.isEmpty()){ //Check for a named blessing.
|
||||||
|
if(!player.hasBlessing(condition.hasBlessing)){
|
||||||
|
if(!condition.not) return false;
|
||||||
|
} else if(condition.not) return false;
|
||||||
}
|
}
|
||||||
if (condition.actorID != 0) { //Check for actor ID.
|
if (condition.actorID != 0) { //Check for actor ID.
|
||||||
if (!stage.lookForID(condition.actorID)) {
|
if (!stage.lookForID(condition.actorID)) {
|
||||||
|
|||||||
31
forge-gui-mobile/src/forge/adventure/util/NavArrowActor.java
Normal file
31
forge-gui-mobile/src/forge/adventure/util/NavArrowActor.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package forge.adventure.util;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.Sprite;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.Actor;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
|
public class NavArrowActor extends Actor {
|
||||||
|
|
||||||
|
Sprite texture;
|
||||||
|
public float navTargetAngle = 0.0f;
|
||||||
|
|
||||||
|
public NavArrowActor() {
|
||||||
|
//TODO: Expand compass sprite to have color coded arrows, swap sprites based on distance to target
|
||||||
|
Array<Sprite> textureAtlas = Config.instance().getAtlas("maps/tileset/compass.atlas").createSprites("compass");
|
||||||
|
if (textureAtlas.isEmpty()) {
|
||||||
|
System.out.print("NavArrow sprite not found");
|
||||||
|
}
|
||||||
|
texture = textureAtlas.get(0);
|
||||||
|
setHeight(texture.getRegionHeight());
|
||||||
|
setWidth(texture.getRegionWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Batch batch, float parentAlpha) {
|
||||||
|
if (texture == null)
|
||||||
|
return;
|
||||||
|
//TODO: Simplify params somehow for readability? All this does is spin the image around the player.
|
||||||
|
batch.draw(texture, getX()-texture.getWidth()/2, getY()-texture.getHeight()/2 ,(texture.getWidth()*texture.getScaleX()/2),(texture.getHeight()*texture.getScaleY()/2), texture.getWidth(), texture.getHeight(), texture.getScaleX(), texture.getScaleY(), navTargetAngle);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ public class Paths {
|
|||||||
public static final String HEROES = "world/heroes.json";
|
public static final String HEROES = "world/heroes.json";
|
||||||
public static final String POINTS_OF_INTEREST = "world/points_of_interest.json";
|
public static final String POINTS_OF_INTEREST = "world/points_of_interest.json";
|
||||||
public static final String ITEMS = "world/items.json";
|
public static final String ITEMS = "world/items.json";
|
||||||
|
public static final String QUESTS = "world/quests.json";
|
||||||
public static final String SKIN = "skin/ui_skin.json";
|
public static final String SKIN = "skin/ui_skin.json";
|
||||||
public static final String ITEMS_EQUIP = "skin/equip.png";
|
public static final String ITEMS_EQUIP = "skin/equip.png";
|
||||||
public static final String ITEMS_ATLAS = "sprites/items.atlas";
|
public static final String ITEMS_ATLAS = "sprites/items.atlas";
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public class World implements Disposable, SaveFileContent {
|
|||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
private boolean worldDataLoaded = false;
|
private boolean worldDataLoaded = false;
|
||||||
private Texture globalTexture = null;
|
private Texture globalTexture = null;
|
||||||
|
private int nextQuestId;
|
||||||
|
|
||||||
public Random getRandom() {
|
public Random getRandom() {
|
||||||
return random;
|
return random;
|
||||||
@@ -114,6 +115,7 @@ public class World implements Disposable, SaveFileContent {
|
|||||||
mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(), this.data.height / getChunkSize());
|
mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(), this.data.height / getChunkSize());
|
||||||
mapPoiIds.load(saveFileData.readSubData("mapPoiIds"));
|
mapPoiIds.load(saveFileData.readSubData("mapPoiIds"));
|
||||||
seed = saveFileData.readLong("seed");
|
seed = saveFileData.readLong("seed");
|
||||||
|
nextQuestId = saveFileData.readInt("nextQuestId");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -129,6 +131,7 @@ public class World implements Disposable, SaveFileContent {
|
|||||||
data.store("mapObjectIds", mapObjectIds.save());
|
data.store("mapObjectIds", mapObjectIds.save());
|
||||||
data.store("mapPoiIds", mapPoiIds.save());
|
data.store("mapPoiIds", mapPoiIds.save());
|
||||||
data.store("seed", seed);
|
data.store("seed", seed);
|
||||||
|
data.store("nextQuestId", nextQuestId);
|
||||||
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
@@ -899,6 +902,10 @@ public class World implements Disposable, SaveFileContent {
|
|||||||
return mapPoiIds.findPointsOfInterest(name);
|
return mapPoiIds.findPointsOfInterest(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<PointOfInterest> getAllPointOfInterest(){
|
||||||
|
return mapPoiIds.getAllPointOfInterest();
|
||||||
|
}
|
||||||
|
|
||||||
public int getChunkSize() {
|
public int getChunkSize() {
|
||||||
return (Scene.getIntendedWidth() > Scene.getIntendedHeight() ? Scene.getIntendedWidth() : Scene.getIntendedHeight()) / data.tileSize;
|
return (Scene.getIntendedWidth() > Scene.getIntendedHeight() ? Scene.getIntendedWidth() : Scene.getIntendedHeight()) / data.tileSize;
|
||||||
}
|
}
|
||||||
@@ -919,4 +926,8 @@ public class World implements Disposable, SaveFileContent {
|
|||||||
}
|
}
|
||||||
return globalTexture;
|
return globalTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNextQuestId() {
|
||||||
|
return nextQuestId++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Flame Sword
|
||||||
|
Types:Artifact
|
||||||
|
A:AB$ DealDamage | ActivationLimit$ 1 | Cost$ PayShards<3> | ActivationZone$ Command | ValidTgts$ Creature,Player,Planeswalker | NumDmg$ Z | SubAbility$ Eject | SpellDescription$ Deal 3 damage to any target. If the target is a tapped creature, deal 5 damage to it instead.
|
||||||
|
SVar:X:3
|
||||||
|
SVar:Y:Targeted$Valid Creature.tapped/Times.2
|
||||||
|
SVar:Z:SVar$X/Plus.Y
|
||||||
|
SVar:Eject:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
|
||||||
|
Oracle:{M}{M}{M}: Flame Sword deals 3 damage to any target, or 5 damage to target tapped creature.
|
||||||
|
|
||||||
@@ -7,17 +7,17 @@
|
|||||||
<tileset firstgid="10113" source="../tileset/buildings.tsx"/>
|
<tileset firstgid="10113" source="../tileset/buildings.tsx"/>
|
||||||
<layer id="13" name="subsublaag" width="37" height="23">
|
<layer id="13" name="subsublaag" width="37" height="23">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJxjYBgFo4Ay4MY50C7ABF4D7KYPWMSQ3URqmD1jpcg5YPCBAbu7SHUHOqaGuyh1kyPUHY5UdBc6YOOFYGLcA7OfQwBBU9tdv3ggmFjALYDKh7kNOS4PsFPPfchgGlp6d6RB/AxVMJDlJ668NxjL9MHqJlq6C5RnYZhUN9HDXaS4iZaAVPeAAK3dFEaG+bR2EznmD8Z8NxgBAK1JHpE=
|
eJxjYBgFo4Ay4MY50C7ABF4D7KYPWMSQ3URqmD1jpcg5YPCBAbu7SHUHOqaGu6jtJmq4Cx2w8UIwKe7hEKCdu37xQDCxgFsAtzth+AA79dyHDKahpXdHGsTPUAUDWX7iynuDsUwfrG6ipbtAeRaGSXUTPdxFiptoCUh1DwjQ2k1hZJhPazeRY/5gzHeDEQAAOM4lLQ==
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<layer id="10" name="sublaag" width="37" height="23">
|
<layer id="10" name="sublaag" width="37" height="23">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJy1ljFuwzAMRbXYgZO0yNy9BykKdM8tcoVO7Sk6+iw5SqfMOUJBKAQ+2E9Sip0PfNimbOqZVOSMT6WMgc8bbnvP+/N6bmW5DNUeE15jftQjmdi9NhYx4TUT4znt/zOpIib2zky7A3fEhHWyPWtxJpyfxRiLcqC/xlK+xzbGpUyWy84p5yKN47nH5+lnqs56x2pi878N1dEzl6Gkipgk7uWPevF7m/dztz6TjouytS162dfj66aacWVidUFG+a2rkUfGtjdn+ZXrmONQJmvLdC3V2XPKosetWZtLmMQfU7XH5DGitKbeeAsHep7qPitcvXWy8th6eHDv72XC9YY9XMJkv0XKZHPq/Npj23ePifUu4hMOey352XtGTBpnc7I81va/A2MqTp2UB+e/Fh7vte49rG6aO2PSHtvY2kzz1MfEPC/gamHCddXC8wgu27seDutobbN1LMI9AMfk+yI58Xtzjz2We/wHYwbUuA==
|
eJy1lk1OAzEMhbNp0RRKgV4AuEolzsICLlHuwHLOwmm67hGQlVo8np7z07SWnqo4E+cb25N0uU5pWdDPjRY/s7u/nFpZDousiAnHGB/tmkzqWfaVmHCsTPG838U1KzGpd1Z2+6BVYsI8cc1aVDPcX/kUi3OgehhHmZhLMSCLWcRbY/qesmq1K+XE9bxN6QX0utXralZiMn/EpGpxeEzpY/O3Zv+kuUaYfJ7rpnrbcmQ8n5v/+WWumqm8IKN96y7ksbnVSbX4zvV1YutlYjHTMWXV1jmL/66oN0eYTG9TVsQUMaJ5TqP5Fg7UPOVz1rh688QWsfXw4Nnfy4T9hjUcYeK7yJk4pu/vNea6R0yqdiU+4+CxxVfvWWJyv9pTxWHxfwfFlII8OQ/uf0za3ys/e1TePHaNyWvMvkszzVMfk9I8wNXChH3VwnMNLq5dDwer1Nuqj83wDMA5u18sJt435yhiOUe/IfLYdQ==
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<layer id="9" name="slim" width="37" height="23">
|
<layer id="9" name="slim" width="37" height="23">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJydlm1ugzAMhpnWrYS20i6xK+wGKRUn2Q12JPp1iF1j3Z9J/eIM1X4Mi7zjxRhKa8lKlID92EmcRFFb5q7W1FVjnvoZ9UUWrlItzzNb7xFhWcdRtI0r33nZFsEv+kOZxM4m2BK7zHQLM/KzL/UY2kPo+8B7HMjEeQYTK2IH+8G1bYjKv6dSz0FX5bef40o9zS3jqgWTFTPneR18Tl5sFXuimgn7iLklJ2DKyDZ0T32JmfMv/IWKvYtJ/F2m7Xwjl7wWwgJBnhDTSsWVGWuoxeLxlActC9pH/7E+Nb+RfHAO87heS50TLfOwzpqpoFh5DQ6KBTxfSRTtSL+TNufWiE+zQDVT5przj7Om6rUQ+ZhU7U/g2BlMfkB+upg8zVn/8Xk7G9+8jmsuEWGD9gmfi6PB9D6t/KO9pl2CtRQei58lNeb1HpxTy76xf7GHpU1CPCLWmbnG3sUEPzhr6KNmw6b4Z+2qJRD0UaMQC9fmTdw+Ozq+Qq2NFYNmSxQPc2k+ML492N/pbzUPzgEkj+t6CMX90pUry0/fGI/z2rOeXF0D9q55jzN35pr7kGNhVtRQHrdiRn7028HKlYhX/tMrTJZ/K0/eyInYuRg+YT9XMWAedymPjYy3DhiSjnVkJtQs7H9mEgGTrvPwb9Ur5gIL1o3fOSxsHz7xb6bs4/4r1HifwPZo1t6P2B+pa74fMK/reW74Hlq7u7h+jXcP5wRvO9TuZdx8FxY9vm/h4X/47Ipw3Ho/3nuX3cqk3+jW+Rqqf6YK8do=
|
eJylVltuwjAQTFVa2RQEp+kNTFBO0o/Sa4VHbxUeOQPqR7NKRhlvNg/alUY2MfbOjtdrJ0nXNr5F6utvgfoZ9cW2voa216WNv5hwObok+Xa177xqy8Yv+lM5yTqnZi1Zlzk9whn6FBUuTXtu+qHhe5nIiXUGJwZiB/ez764hkLnXCrcGB9f+J9DY3tUtOFkxs87Hxufb2oast3ddTsgj5s2aZLQ2UFBfYmb9hX+pYu/jJP7ui67e0NLaC9YJMR1UXFnPvDFOgXTQtqU86jPRgzXMXbuXWhNtm2afNaeSYuU90Ps0ZNeX+Pe3EZ/mAmhOmY/Hn5cx9F7APldJsqvwtbLHwwR9OFfBRzQONGbN4/N2o//IfLTMS/QChozPxcV3c+ljUftHOwZwAcR2SrexPEqNcZ2DG2q1bieqA9LO17FOGn26j3GCH5w19FGzsab4Z/TVEhj6qFGIhWvzydlnR587655l09zmig/zghU+7r8/2f/T8zUfnE1Y7tp6COB+6dPK8jP0jb/z3jOudKcVPr7HmXfm4zzkWJgraih/t2KGPvrtYGklFpT/1OBkxa510b+DoYn4vhs+wSlXMWAcdyl/mxlvHXCY9+wjc0LNQv4zJzFw0nUe/q2awbzABftmvXP0+vCJuZlaH/df6e19sQxrz5bdfER+pD5+P2Bc1/Pc8N2nxVReP8a7hzXB2w61e+/id2E54PsRPjyHz64Yx63zccpd9l9DvnKtts7XVPwCwzvlKg==
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<layer id="12" name="clutter" width="37" height="23">
|
<layer id="12" name="clutter" width="37" height="23">
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<property name="spriteLayer" type="bool" value="true"/>
|
<property name="spriteLayer" type="bool" value="true"/>
|
||||||
</properties>
|
</properties>
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJzNllFSgzAQhqMzVVLF6aN30Veo0xN4F0/hAfTVar2Rj7SVYzRr+IdlS8hGcOo/swMtIfny77JgzO9U2va8sN3fp5KWqbRtxK6N2ZdcYwqmoXEh7Wc++uYKMYXW/MiM2Yj4zMYxSe0SeCgeXFwtjHlx415dvDmeWukTjX3P4kwpPJzp7syYexeV1ftEY6UHlcLbIZ6f/bnjt/X7JbYUn0L6mvsjfARnjEUyLxu/UoV80b2I22vPJX3UMNH5tskVmOpEb7jHfVyos1WkhiBioXrCflBLF3kbUqhpLuwHAd+Ii/K3znRMqBti4s8PKcSEHJ/nvodAtJ+n3M8jfSsiLJypavJG862atbh/sqfz57QQ47E+zUn9bWe7/21ZjWj6Mfzi/kvx/ooc03G+OA7MQb7JGpP7XdpjFvK5ZmuFxD0KifKFORF9tc9zKX2AzxvGE3rmSgV3SLLuea2jX3NP/0qolXXW7cXon9yLvvym6PEynQ35Rg3KdccyjdHQenTt+Wb4uoZ3qm/ZfWSeU/g3Rv/hGx/SvBc0740pdQCOCZmI
|
eJzFVltSwzAMNHxATCeQ+8Bvkk5PwCG4AafgAPDLq7fqgx4Da5KdKGpty9hMd0bjpPZIq5Wl1Ji/obPTc2vn7+eCllNnJ4vt5eQlY5TgFDqXwgnm4+SL+VUZ8y1sXeVxktgl8CFbOls0xry6c2/O3h2fg1InOvtZpXMM8eGc7i+MeXC2sXqd6KzUYKPQNsSHsHfrjx3yJW4pOsUAHcEzxkVy7ke9cvB0N3+XOmo44ZlqRZygUQqgcQyryB0CiAvdJ+SDu3RVT6ZBH8iD8vwYOcc4QZOlPe4fHyfMjst6WAHK57ke/PC7SdZG9OGcSJPtqM/KznOVfSf7tBXnEZ980nzb2flv29G431D/QK+e+ZHg8xU1pvWmOTb4IN0WzdxkvrLm0PnAYvnANfKB6gWfMF7DU7WUOkBnaB3quU7B2wcek1bef5jXXNP/Ap/HfBZjfnItTtU3BY/X6dxQb9xBGTeXUw5C8Wjv5Ta8r+Fb6n/MPuLnHPrloJQuJaD5Lmi+GyXxCxKjjW8=
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<objectgroup id="11" name="obj">
|
<objectgroup id="11" name="obj">
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
compass.png
|
||||||
|
size: 50,50
|
||||||
|
format: RGBA8888
|
||||||
|
filter: Nearest,Nearest
|
||||||
|
repeat: none
|
||||||
|
compass
|
||||||
|
xy: 1,1
|
||||||
|
size: 48,48
|
||||||
BIN
forge-gui/res/adventure/Shandalar/maps/tileset/compass.png
Normal file
BIN
forge-gui/res/adventure/Shandalar/maps/tileset/compass.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -420,3 +420,6 @@ GreenLeaf2
|
|||||||
SearchPost
|
SearchPost
|
||||||
xy: 384, 63
|
xy: 384, 63
|
||||||
size: 16, 16
|
size: 16, 16
|
||||||
|
LogBook
|
||||||
|
xy: 240, 912
|
||||||
|
size: 16, 16
|
||||||
@@ -118,9 +118,9 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "statistic",
|
"name": "logbook",
|
||||||
"style":"menu",
|
"style":"menu",
|
||||||
"text": "[%120][+Status]",
|
"text": "[%120][+Logbook]",
|
||||||
"binding": "Status",
|
"binding": "Status",
|
||||||
"width": 48,
|
"width": 48,
|
||||||
"height": 36,
|
"height": 36,
|
||||||
|
|||||||
@@ -104,13 +104,11 @@
|
|||||||
"x": 416,
|
"x": 416,
|
||||||
"y": 146
|
"y": 146
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "statistic",
|
"name": "logbook",
|
||||||
"style":"menu",
|
"style":"menu",
|
||||||
"text": "[%120][+Status]",
|
"text": "[%120][+Logbook]",
|
||||||
"binding": "Status",
|
|
||||||
"width": 64,
|
"width": 64,
|
||||||
"height": 36,
|
"height": 36,
|
||||||
"x": 416,
|
"x": 416,
|
||||||
|
|||||||
@@ -106,9 +106,9 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "statistic",
|
"name": "logbook",
|
||||||
"style":"menu",
|
"style":"menu",
|
||||||
"text": "[%120][+Status]",
|
"text": "[%120][+Logbook]",
|
||||||
"binding": "Status",
|
"binding": "Status",
|
||||||
"width": 64,
|
"width": 64,
|
||||||
"height": 32,
|
"height": 32,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cards",
|
"name": "cards",
|
||||||
"x": 5,
|
"x": 5,
|
||||||
"y": 5,
|
"y": 20,
|
||||||
"width": 260,
|
"width": 260,
|
||||||
"height": 405
|
"height": 405
|
||||||
},
|
},
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"text": "A Street Market",
|
"text": "A Street Market",
|
||||||
"width": 48,
|
"width": 48,
|
||||||
"height": 20,
|
"height": 20,
|
||||||
"x": 200,
|
"x": 0,
|
||||||
"y": 0
|
"y": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
87
forge-gui/res/adventure/Shandalar/ui/quests.json
Normal file
87
forge-gui/res/adventure/Shandalar/ui/quests.json
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"width": 480,
|
||||||
|
"height": 270,
|
||||||
|
"yDown": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"name": "lastScreen",
|
||||||
|
"width": 480,
|
||||||
|
"height": 270
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Window",
|
||||||
|
"name": "scrollWindow",
|
||||||
|
"style": "paper",
|
||||||
|
"x": 15,
|
||||||
|
"y": 18,
|
||||||
|
"width": 400,
|
||||||
|
"height": 235,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Table",
|
||||||
|
"name": "questList",
|
||||||
|
"x": 20,
|
||||||
|
"y": 22,
|
||||||
|
"width": 390,
|
||||||
|
"height": 220,
|
||||||
|
"fontColor":"black"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Table",
|
||||||
|
"name": "questDetails",
|
||||||
|
"x": 20,
|
||||||
|
"y": 22,
|
||||||
|
"width": 390,
|
||||||
|
"height": 220,
|
||||||
|
"fontColor":"black"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "abandonQuest",
|
||||||
|
"text": "Abandon Quest",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 20,
|
||||||
|
"y": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "trackQuest",
|
||||||
|
"text": "Track Quest",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 150,
|
||||||
|
"y": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "backToList",
|
||||||
|
"text": "Quest List",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 280,
|
||||||
|
"y": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "return",
|
||||||
|
"text": "tr(lblBack)",
|
||||||
|
"binding": "Back",
|
||||||
|
"width": 60,
|
||||||
|
"height": 30,
|
||||||
|
"x": 420,
|
||||||
|
"y": 224
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "status",
|
||||||
|
"text": "Status",
|
||||||
|
"binding": "Status",
|
||||||
|
"width": 60,
|
||||||
|
"height": 30,
|
||||||
|
"x": 420,
|
||||||
|
"y": 184
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
86
forge-gui/res/adventure/Shandalar/ui/quests_portrait.json
Normal file
86
forge-gui/res/adventure/Shandalar/ui/quests_portrait.json
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
{
|
||||||
|
"width": 270,
|
||||||
|
"height": 480,
|
||||||
|
"yDown": true,
|
||||||
|
"elements": [
|
||||||
|
{
|
||||||
|
"type": "Image",
|
||||||
|
"name": "lastScreen",
|
||||||
|
"width": 270,
|
||||||
|
"height": 480
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Window",
|
||||||
|
"name": "scrollWindow",
|
||||||
|
"style": "paper",
|
||||||
|
"x": 4,
|
||||||
|
"y": 4,
|
||||||
|
"width": 262,
|
||||||
|
"height": 419
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Table",
|
||||||
|
"name": "questList",
|
||||||
|
"x": 8,
|
||||||
|
"y": 10,
|
||||||
|
"width": 258,
|
||||||
|
"height": 413
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Table",
|
||||||
|
"name": "questDetails",
|
||||||
|
"x": 8,
|
||||||
|
"y": 10,
|
||||||
|
"width": 258,
|
||||||
|
"height": 413
|
||||||
|
"fontColor":"black"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "abandonQuest",
|
||||||
|
"text": "Abandon Quest",
|
||||||
|
"width": 250,
|
||||||
|
"height": 30,
|
||||||
|
"x": 10,
|
||||||
|
"y": 14
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "trackQuest",
|
||||||
|
"text": "Track Quest",
|
||||||
|
"width": 250,
|
||||||
|
"height": 30,
|
||||||
|
"x": 10,
|
||||||
|
"y": 54
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "backToList",
|
||||||
|
"text": "Quest List",
|
||||||
|
"width": 250,
|
||||||
|
"height": 30,
|
||||||
|
"x": 10,
|
||||||
|
"y": 94
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "return",
|
||||||
|
"text": "tr(lblBack)",
|
||||||
|
"binding": "Back",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 135,
|
||||||
|
"y": 440
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "status",
|
||||||
|
"text": "Status",
|
||||||
|
"binding": "Status",
|
||||||
|
"width": 130,
|
||||||
|
"height": 30,
|
||||||
|
"x": 5,
|
||||||
|
"y": 440
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -122,9 +122,9 @@
|
|||||||
"name": "return",
|
"name": "return",
|
||||||
"text": "tr(lblBack)",
|
"text": "tr(lblBack)",
|
||||||
"binding": "Back",
|
"binding": "Back",
|
||||||
"width": 100,
|
"width": 80,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 345,
|
"x": 395,
|
||||||
"y": 224
|
"y": 224
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
"text": "[%120][+AWARD]",
|
"text": "[%120][+AWARD]",
|
||||||
"width": 30,
|
"width": 30,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 315,
|
"x": 285,
|
||||||
"y": 224
|
"y": 224
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -169,9 +169,15 @@
|
|||||||
"x": 394,
|
"x": 394,
|
||||||
"y": 60
|
"y": 60
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "Table",
|
"type": "TextButton",
|
||||||
"font": "default"
|
"name": "quests",
|
||||||
|
"text": "Quests",
|
||||||
|
"binding": "Status",
|
||||||
|
"width": 80,
|
||||||
|
"height": 30,
|
||||||
|
"x": 315,
|
||||||
|
"y": 224
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,11 +113,21 @@
|
|||||||
"name": "return",
|
"name": "return",
|
||||||
"text": "tr(lblBack)",
|
"text": "tr(lblBack)",
|
||||||
"binding": "Back",
|
"binding": "Back",
|
||||||
"width": 230,
|
"width": 115,
|
||||||
|
"height": 30,
|
||||||
|
"x": 155,
|
||||||
|
"y": 440
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "TextButton",
|
||||||
|
"name": "quests",
|
||||||
|
"text": "Quests",
|
||||||
|
"binding": "Status",
|
||||||
|
"width": 115,
|
||||||
"height": 30,
|
"height": 30,
|
||||||
"x": 35,
|
"x": 35,
|
||||||
"y": 440
|
"y": 440
|
||||||
},
|
}
|
||||||
{
|
{
|
||||||
"type": "TextButton",
|
"type": "TextButton",
|
||||||
"name": "toggleAward",
|
"name": "toggleAward",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -434,9 +434,9 @@
|
|||||||
"equipmentSlot": "Left",
|
"equipmentSlot": "Left",
|
||||||
"iconName": "FlameSword",
|
"iconName": "FlameSword",
|
||||||
"effect": {
|
"effect": {
|
||||||
"opponent": {
|
"startBattleWithCardInCommandZone": [
|
||||||
"lifeModifier": -5
|
"Flame Sword"
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
5669
forge-gui/res/adventure/Shandalar/world/quests.json
Normal file
5669
forge-gui/res/adventure/Shandalar/world/quests.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -72,12 +72,12 @@
|
|||||||
"rewards": [
|
"rewards": [
|
||||||
{
|
{
|
||||||
"count":6,
|
"count":6,
|
||||||
"cardText": "deathtouch|fear|intimidate|menace|ninjitsu|regenerate\b",
|
"cardText": "deathtouch|fear|intimidate|menace|ninjutsu|regenerate\b",
|
||||||
"colors": ["black"]
|
"colors": ["black"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"count":2,
|
"count":2,
|
||||||
"cardText": "deathtouch|fear|intimidate|menace|ninjitsu|regenerate\b"
|
"cardText": "deathtouch|fear|intimidate|menace|ninjutsu|regenerate\b"
|
||||||
}]
|
}]
|
||||||
},{
|
},{
|
||||||
"name":"Black6",
|
"name":"Black6",
|
||||||
@@ -136,12 +136,12 @@
|
|||||||
"rewards": [
|
"rewards": [
|
||||||
{
|
{
|
||||||
"count":6,
|
"count":6,
|
||||||
"cardText": "flying|prowess|unblockable|hexproof|shroud|morph|ninjitsu|phas(ing|(es (in|out)))",
|
"cardText": "flying|prowess|unblockable|hexproof|shroud|morph|ninjutsu|phas(ing|(es (in|out)))",
|
||||||
"colors": ["blue"]
|
"colors": ["blue"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"count":2,
|
"count":2,
|
||||||
"cardText": "flying|prowess|unblockable|hexproof|shroud|morph|ninjitsu|phas(ing|(es (in|out)))"
|
"cardText": "flying|prowess|unblockable|hexproof|shroud|morph|ninjutsu|phas(ing|(es (in|out)))"
|
||||||
}]
|
}]
|
||||||
},{
|
},{
|
||||||
"name":"Blue4",
|
"name":"Blue4",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ T:Mode$ LandPlayed | ValidCard$ Card.ExiledWithSourceLKI | TriggerZones$ Battlef
|
|||||||
SVar:TrigDraw:DB$ Draw | SubAbility$ DBConvert
|
SVar:TrigDraw:DB$ Draw | SubAbility$ DBConvert
|
||||||
SVar:DBConvert:DB$ SetState | Mode$ Transform
|
SVar:DBConvert:DB$ SetState | Mode$ Transform
|
||||||
AlternateMode:DoubleFaced
|
AlternateMode:DoubleFaced
|
||||||
Oracle:More Than Meets the Eye {1}{R}{G} (You may cast this card converted for {1}{R}{G}.)\nWhenever Prowl attacks, exile up to one other target tapped creature or Vehicle. For as long as that card remains exiled, its owner may play it.\nWhenever a player plays a card exiled with Prowl, you draw a card and convert Prowl.
|
Oracle:More Than Meets the Eye {2}{W} (You may cast this card converted for {2}{W}}.)\nWhenever Prowl attacks, exile up to one other target tapped creature or Vehicle. For as long as that card remains exiled, its owner may play it.\nWhenever a player plays a card exiled with Prowl, you draw a card and convert Prowl.
|
||||||
|
|
||||||
ALTERNATE
|
ALTERNATE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user