1 /*
2  *  CVS: $Id: Dialog.java,v 1.8 2004/07/25 19:07:20 marcus Exp $
3  * 
4  *  This file is part of JZuul.
5  *
6  *  JZuul is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10 *
11 *  JZuul is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with Zuul; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 * 
20 *  Copyrigth 2004 by marcus, leh
21 * 
22 */
23
24package org.jzuul.engine;
25
26import java.awt.event.ActionEvent;
27import java.awt.event.ActionListener;
28import java.util.Iterator;
29import java.util.List;
30import java.util.Vector;
31
32/**
33 * Dialog bildet einen Dialog mit einem Character Objekt ab
34 * 
35 * Ein Dialog ist in Phasen aufgeteilt, wobei für jede Phase eine Anzahl von Aussagen
36 * des Players vorhanden sein muss und eine Anzahl von Antworten auf die Aussage.
37 * über die Methode talk wird ein Dialog initiert.
38 * 
39 * 
40 * @version $Revision: 1.8 $
41  */
42public class Dialog {
43    /**
44     * Ein ActionListener der Benutzt wird um die Auswahl der Dialoge 
45     * festzustellen und an den Charakter zu übergeben.
46     */
47    private class AuswahlListener implements ActionListener {
48        /**
49         * Die Methode die von dem Gui aufgerufen wird um
50         * die Auswahl zu übergeben.
51         * 
52         * @param e ein AWT ActionEvent
53         */
54        public void actionPerformed(ActionEvent e) {
55            Vector v = getPhaseVector(currentPhase);
56            DialogObject retval = null;
57            Engine.gui.resetInput();
58            try {
59                int auswahl = Integer.parseInt(e.getActionCommand());
60                auswahl--;
61                if ((auswahl >= v.size()) || (auswahl < 0)) {
62                    Engine.gui.println((auswahl + 1) + Messages.getString("DIALOG_NO_VALID_NUMBER")); //$NON-NLS-1$
63                } else {
64                    retval = (DialogObject) v.get(auswahl);
65                }
66            } catch (NumberFormatException ex) {
67                Engine.gui.println(Messages.getString("DIALOG_HAVE_TO_ENTER_NUMBER")); //$NON-NLS-1$
68            }
69                    if (retval != null) {
70                talk(retval);
71            }
72        }
73    }
74
75    /**
76     * Die Verschiedenen Dialogphasen. Der Vector enthällt pro Phase wiederum einen Vector von
77     * DialogObjects
78     */
79    Vector phases;
80    
81    /**
82     * Dieser Vector enthällt alle DialogObjects unter ihrere Id
83     */
84    Vector dialogs;
85    
86    /**
87     * Die aktuelle Phase des Dialoges (default ist 1)
88     */
89    int currentPhase;
90    
91    /**
92     * Das Character Objekt der diesen Dialog füht
93     */
94    Character character;
95    
96    /**
97     * Eine Liste von GameObject Namen die als Vorbedingungen 
98     * für diesen Dialog gelten
99     */
00    List preconditions;
01
02    /**
03     * Konstruktor
04     *
05     */
06    public Dialog() {
07        this.phases = new Vector(10);
08        this.dialogs = new Vector(10);
09        this.preconditions = new Vector();
10        currentPhase = 1;
11    }
12
13    /**
14     * Fügt ein neues DialogObject in den Dialog ein
15     * 
16     * @param phase Die Dialogphase für diesen Dialog
17     * @param id            Eine eindeutige ID für das DialogObject
18     * @param playerSentence    Die Aussage des Spielers
19     * @param npcAnswer         Die Antwort des Characters
20     * @param type                      den DialogObject type
21     * @param nextPhase         Die nächste Phase, falls type DialogObject.DIALOG_CONTINUE ist, 0 sonst.
22     * @see org.jzuul.engine.DialogObject
23     */
24    public void addDialog(int phase, int id, String playerSentence, String npcAnswer, int type, int nextPhase) {
25        DialogObject dialog = new DialogObject(phase, id, playerSentence, npcAnswer, nextPhase, type);
26        this.addToPhase(phase, dialog);
27        if (id > dialogs.size()) {
28            dialogs.setSize(id);
29        }
30        this.dialogs.add(id, dialog);
31    }
32
33    /**
34     * Fügt ein existierendes DialogObject in eine andere Phase
35     * 
36     * @param phase Die Dialogphase dem das DialogObject hinzugefügt werden soll
37     * @param id            Die id des existierenden DialogObjects
38     */
39    public void addDialog(int phase, int id) {
40        this.addToPhase(phase, (DialogObject) dialogs.get(id));
41    }
42
43    /**
44     * Fügt ein DialogObject in die Phase phase ein
45     * 
46     * @param phase Die Dialogphase für diesen Dialog
47     * @param dialog    Das DialogObject
48     */
49    protected void addToPhase(int phase, DialogObject dialog) {
50        this.getPhaseVector(phase).add(dialog);
51    }
52
53    /**
54     * Zugriff auf alle DialogObject Objekte einer Phase
55     * 
56     * @param phase Die Phase aus der die Objekte geholte werden sollen
57     * @return  Einen Vector aus den DialogObject Objekten einer Phase
58     */
59    protected Vector getPhaseVector(int phase) {
60        if (this.phases.size() < phase) {
61            this.phases.setSize(phase+1);
62        }
63
64        if (this.phases.get(phase) != null) {
65            return (Vector) this.phases.get(phase);
66        } else {
67            Vector newVec = new Vector();
68            this.phases.add(phase, newVec);
69            return newVec;
70        }
71    }
72
73    /**
74     * Die Hauptmethode, wird von dem Befehlt "talk" aufgerufen.
75     * Sie setzt dem Engine.gui eine AuswahlListener als neuen
76     * ActionListener und gibt die Auswahl möglicher Sätze aus. 
77     * 
78     * @return  bei nicht kritischen fehlern true
79     */
80    public boolean talk() {
81        if (this.dialogs.size() > 0 &&  this.phases.size() > 0 ) {
82            this.printAuswahl();
83            Engine.gui.setActionListener(new AuswahlListener());
84            return true;
85        } else {
86            return false;
87        }
88    }
89
90    /**
91     * Diese Methode wird von dem AuswahlListener Objekt aufgerufen
92     * nachdem der Spieler seine Auswahl getätigt hat.
93     * 
94     * @param selected  das zu dem ausgewählten Satz gehörende DialogObject
95     */
96    public void talk(DialogObject selected) {
97        if (selected == null)
98            throw new IllegalArgumentException("Character.talk called with selected==null"); //$NON-NLS-1$
99
00        Engine.player.say(selected.getPlayerSentence());
01        character.say(selected.getNpcAnswer());
02        if (selected.getType() == Event.DIALOG_CONTINUE) {
03            this.currentPhase = selected.getNextPhase();
04        }
05        this.character.pushAnswer(selected.getType());
06    }
07
08    /**
09     * Gibt die Auswahl der möglichen PlayerSentences einer Phase aus.
10     */
11    public void printAuswahl() {
12        Vector v = getPhaseVector(this.currentPhase);
13        int index = 1;
14        Engine.gui.println("-----------------------------------------------"); //$NON-NLS-1$
15        for (Iterator i = v.iterator(); i.hasNext();) {
16            DialogObject dialog = (DialogObject) i.next();
17            Engine.gui.println(index + ") " + dialog.getPlayerSentence()); //$NON-NLS-1$
18            index++;
19        }
20        Engine.gui.println("-----------------------------------------------"); //$NON-NLS-1$
21    }
22
23    /**
24     * Fügt einen GameObject Namen als Vorbedingung hinzu
25     * 
26     * @param objName   der Name eines GameObjects das Vorbedingung zu diesem Dialog ist
27     */
28    public void addPrecondition(String objName) {
29        this.preconditions.add(objName);
30    }
31    
32    /**
33     * Die Liste der Vorbedingungen
34     * 
35     * @return  List of Strings (die Namen der GameObjects)
36     */
37    public List getPreconditions() {
38        return this.preconditions;
39    }
40    
41    /**
42     * Setzt das Character Objekt das diesen Dialog führt
43     * 
44     * @param character das Character Objekt
45     */
46    public void setCharacter(Character character) {
47        this.character = character;
48    }
49    
50    /**
51     * Setzt die Dialogphase auf 1 zurück
52     */
53    public void resetPhase() {
54        this.currentPhase = 1;
55    }
56
57}
58