Package games.stendhal.server.maps.quests

Source Code of games.stendhal.server.maps.quests.KanmararnSoldiers

/* $Id: KanmararnSoldiers.java,v 1.72 2011/05/01 19:50:05 martinfuchs Exp $ */
/***************************************************************************
*                   (C) Copyright 2003-2010 - Stendhal                    *
***************************************************************************
***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************/
package games.stendhal.server.maps.quests;

import games.stendhal.common.parser.Sentence;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.events.TurnListener;
import games.stendhal.server.entity.Entity;
import games.stendhal.server.entity.item.Corpse;
import games.stendhal.server.entity.item.Item;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.ChatCondition;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropInfostringItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseKarmaAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.action.SetQuestAndModifyKarmaAction;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.GreetingMatchesNameCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.OrCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasInfostringItemWithHimCondition;
import games.stendhal.server.entity.npc.condition.PlayerOwnsItemIncludingBankCondition;
import games.stendhal.server.entity.npc.condition.QuestCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestInStateCondition;
import games.stendhal.server.entity.npc.condition.QuestNotCompletedCondition;
import games.stendhal.server.entity.npc.condition.QuestNotInStateCondition;
import games.stendhal.server.entity.player.Player;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import marauroa.common.game.RPObject;
import marauroa.common.game.SlotIsFullException;

import org.apache.log4j.Logger;

/**
* QUEST:
* <p>
* Soldiers in Kanmararn.
*
* NOTE:
* <p>
* It also starts a quest that needs NPC McPegleg that is created. It doesn't
* harm if that script is missing, just that the IOU cannot be delivered and
* hence the player can't get cash
*
* PARTICIPANTS:
* <li> Henry
* <li> Sergeant James
* <li> corpse of Tom
* <li> corpse of Charles
* <li> corpse of Peter
*
* STEPS:
* <li> optional: speak to Sergeant James to get the task to find the map
* <li> talk to Henry to get the task to find some proof that the other 3
* soldiers are dead.
* <li> collect the item in each of the corpses of the three other soldiers
* <li> bring them back to Henry to get the map - bring the map to Sergeant
* James
*
* REWARD:
* <p>
* from Henry:
* <li> you can keep the IOU paper (for quest MCPeglegIOU)
* <li> 2500 XP
* <p>
* from Sergeant James
* <li> steel boots
*
* REPETITIONS:
* <li> None.
*
* @see McPeglegIOU
*/
public class KanmararnSoldiers extends AbstractQuest {

  private static final Logger logger = Logger.getLogger(KanmararnSoldiers.class);

  private static final String QUEST_SLOT = "soldier_henry";

  /**
   * The maximum time (in seconds) until plundered corpses will be filled
   * again, so that other players can do the quest as well.
   */
  private static final int CORPSE_REFILL_SECONDS = 60;



  @Override
  public String getSlotName() {
    return QUEST_SLOT;
  }
 
  /**
   * A CorpseRefiller checks, in regular intervals, if the given corpse.
   *
   * @author daniel
   *
   */
  static class CorpseRefiller implements TurnListener {
    private final Corpse corpse;

    private final String itemName;

    private final String description;

    public CorpseRefiller(final Corpse corpse, final String itemName, final String description) {
      this.corpse = corpse;
      this.itemName = itemName;
      this.description = description;
    }

    public void start() {
      SingletonRepository.getTurnNotifier().notifyInTurns(1, this);
    }

    private boolean equalsExpectedItem(final Item item) {
      if (!item.getName().equals(itemName)) {
        return false;
      }

      if (!item.getDescription().equals(description)) {
        return false;
      }

      return corpse.getName().equals(item.getInfoString());
    }

    public void onTurnReached(final int currentTurn) {
      boolean isStillFilled = false;
      // Check if the item is still in the corpse. Note that somebody
      // might have put other stuff into the corpse.
      for (final RPObject object : corpse.getSlot("content")) {
        if (object instanceof Item) {
          final Item item = (Item) object;
          if (equalsExpectedItem(item)) {
            isStillFilled = true;
          }
        }
      }
      try {
        if (!isStillFilled) {
          // recreate the item and fill the corpse
          final Item item = SingletonRepository.getEntityManager().getItem(
              itemName);
          item.setInfoString(corpse.getName());
          item.setDescription(description);
          corpse.add(item);
          corpse.notifyWorldAboutChanges();
        }
      } catch (final SlotIsFullException e) {
        // ignore, just don't refill the corpse until someone removes
        // the other items from the corpse
        logger.warn("Quest corpse is full: " + corpse.getName());
      }
      // continue the checking cycle
      SingletonRepository.getTurnNotifier().notifyInSeconds(CORPSE_REFILL_SECONDS, this);
    }
  }



  static class HenryQuestNotCompletedCondition implements ChatCondition {
    public boolean fire(final Player player, final Sentence sentence, final Entity npc) {
      return (!player.hasQuest(QUEST_SLOT) || player.getQuest(QUEST_SLOT).equals("start"));
    }
  }

  static class HenryQuestCompletedCondition implements ChatCondition {
    public boolean fire(final Player player, final Sentence sentence, final Entity npc) {
      return (player.hasQuest(QUEST_SLOT) && !player.getQuest(QUEST_SLOT).equals("start"));
    }
  }

  static class GiveMapAction implements ChatAction {
    private boolean bind = false;

    public GiveMapAction(boolean bind) {
      this.bind = bind;
    }

    public void fire(final Player player, final Sentence sentence, final EventRaiser npc) {
      final Item map = SingletonRepository.getEntityManager().getItem("map");
      map.setInfoString(npc.getName());
      map.setDescription("You see a hand drawn map, but no matter how you look at it, nothing on it looks familiar.");
      if (bind) {
        map.setBoundTo(player.getName());
      }
      player.equipOrPutOnGround(map);
      player.setQuest(QUEST_SLOT, "map");
    }
  }


  /**
   * We add text for NPC Henry who will get us on the quest.
   */
  private void prepareCowardSoldier() {
    final SpeakerNPC henry = npcs.get("Henry");

    henry.add(ConversationStates.ATTENDING,
      ConversationPhrases.QUEST_MESSAGES,
      new AndCondition(new QuestNotCompletedCondition(QUEST_SLOT),
               new QuestNotInStateCondition(QUEST_SLOT,"map")),
      ConversationStates.QUEST_OFFERED,
      "Find my #group, Peter, Tom, and Charles, prove it and I will reward you. Will you do it?",
      null);
   
    henry.add(ConversationStates.ATTENDING,
        ConversationPhrases.QUEST_MESSAGES,
        new OrCondition(new QuestCompletedCondition(QUEST_SLOT),
                 new QuestInStateCondition(QUEST_SLOT,"map")),
        ConversationStates.ATTENDING,
        "I'm so sad that most of my friends are dead.",
        null);
   
    henry.add(ConversationStates.QUEST_OFFERED,
      ConversationPhrases.YES_MESSAGES, null,
      ConversationStates.ATTENDING,
      "Thank you! I'll be waiting for your return.",
      new SetQuestAndModifyKarmaAction(QUEST_SLOT, "start", 5.0));

    henry.add(
      ConversationStates.QUEST_OFFERED,
      "group",
      null,
      ConversationStates.QUEST_OFFERED,
      "The General sent five of us to explore this area in search for #treasure. So, will you help me find them?",
      null);

        henry.add(
        ConversationStates.QUEST_OFFERED,
        "treasure",
        null,
        ConversationStates.QUEST_OFFERED,
        "A big treasure is rumored to be #somewhere in this dungeon. Will you help me find my group?",
        null);

    henry.add(ConversationStates.QUEST_OFFERED,
        ConversationPhrases.NO_MESSAGES, null,
        ConversationStates.ATTENDING,
        "OK. I understand. I'm scared of the #dwarves myself.",
        new SetQuestAndModifyKarmaAction(QUEST_SLOT, "rejected", -5.0));
   
    final List<ChatAction> actions = new LinkedList<ChatAction>();
    actions.add(new IncreaseXPAction(2500));
    actions.add(new DropInfostringItemAction("leather legs","tom"));
    actions.add(new DropInfostringItemAction("scale armor","peter"));
    actions.add(new IncreaseKarmaAction(15.0))
    actions.add(new GiveMapAction(false));
   
    henry.add(ConversationStates.IDLE,
        ConversationPhrases.GREETING_MESSAGES,
        new AndCondition(new GreetingMatchesNameCondition(henry.getName()),
            new QuestInStateCondition(QUEST_SLOT, "start"),
            new PlayerHasInfostringItemWithHimCondition("leather legs", "tom"),
            new PlayerHasInfostringItemWithHimCondition("note", "charles"),
            new PlayerHasInfostringItemWithHimCondition("scale armor", "peter")),
        ConversationStates.ATTENDING,
        "Oh my! Peter, Tom, and Charles are all dead? *cries*. Anyway, here is your reward. And keep the IOU.",
        new MultipleActions(actions));

    henry.add(ConversationStates.IDLE,
        ConversationPhrases.GREETING_MESSAGES,
        new AndCondition(new GreetingMatchesNameCondition(henry.getName()),
            new QuestInStateCondition(QUEST_SLOT, "start"),
            new NotCondition(
                new AndCondition(
                    new PlayerHasInfostringItemWithHimCondition("leather legs", "tom"),
                    new PlayerHasInfostringItemWithHimCondition("note", "charles"),
                    new PlayerHasInfostringItemWithHimCondition("scale armor", "peter")))),
        ConversationStates.ATTENDING,
        "You didn't prove that you have found them all!",
        null);

    henry.add(ConversationStates.ATTENDING, Arrays.asList("map", "group", "help"),
        new OrCondition(
          new  QuestCompletedCondition(QUEST_SLOT),
          new AndCondition(new HenryQuestCompletedCondition(),
          new PlayerOwnsItemIncludingBankCondition("map"))),
        ConversationStates.ATTENDING,
        "I'm so sad that most of my friends are dead.", null);

    henry.add(ConversationStates.ATTENDING, Arrays.asList("map"),
        new AndCondition(
          new  QuestNotCompletedCondition(QUEST_SLOT),
          new HenryQuestCompletedCondition(),
          new NotCondition(new PlayerOwnsItemIncludingBankCondition("map"))),
        ConversationStates.ATTENDING,
        "Luckily I drew a copy of the map, but please don't lose this one.",
        new GiveMapAction(true));

    henry.add(ConversationStates.ATTENDING, Arrays.asList("map"),
        new HenryQuestNotCompletedCondition(),
        ConversationStates.ATTENDING,
        "If you find my friends, I will give you the map.", null);
  }

  /**
   * add corpses of ex-NPCs.
   */
  private void prepareCorpses() {
    final StendhalRPZone zone = SingletonRepository.getRPWorld().getZone("-6_kanmararn_city");

    // Now we create the corpse of the second NPC
    final Corpse tom = new Corpse("youngsoldiernpc", 5, 47);
    // he died first
    tom.setStage(4);
    tom.setName("Tom");
    tom.setKiller("a Dwarven patrol");
    // Add our new Ex-NPC to the game world
    zone.add(tom);

    // Add a refiller to automatically fill the corpse of unlucky Tom
    final CorpseRefiller tomRefiller = new CorpseRefiller(tom, "leather legs",
        "You see torn leather legs that are heavily covered with blood.");
    tomRefiller.start();

    // Now we create the corpse of the third NPC
    final Corpse charles = new Corpse("youngsoldiernpc", 94, 5);
    // he died second
    charles.setStage(3);
    charles.setName("Charles");
    charles.setKiller("a Dwarven patrol");
    // Add our new Ex-NPC to the game world
    zone.add(charles);
    // Add a refiller to automatically fill the corpse of unlucky Charles
    final CorpseRefiller charlesRefiller = new CorpseRefiller(charles, "note",
        "You read: \"IOU 250 money. (signed) McPegleg\"");
    charlesRefiller.start();

    // Now we create the corpse of the fourth NPC
    final Corpse peter = new Corpse("youngsoldiernpc", 11, 63);
    // he died recently
    peter.setStage(2);
    peter.setName("Peter");
    peter.setKiller("a Dwarven patrol");
    // Add our new Ex-NPC to the game world
    zone.add(peter);
    // Add a refiller to automatically fill the corpse of unlucky Peter
    final CorpseRefiller peterRefiller = new CorpseRefiller(
        peter,
        "scale armor",
        "You see a slightly rusty scale armor. It is heavily deformed by several strong hammer blows.");
    peterRefiller.start();
  }

  /**
   * add James.
   */
  private void prepareSergeant() {
    final SpeakerNPC james = npcs.get("Sergeant James");

    // quest related stuff
    james.addHelp("Think I need a little help myself. My #group got killed and #one of my men ran away. Too bad he had the #map.");
    james.addQuest("Find my fugitive soldier and bring him to me ... or at least the #map he's carrying.");
    james.addReply("group",
      "We were five, three of us died. You probably passed their corpses.");
    james.addReply(Arrays.asList("one", "henry"),
      "Yes, my youngest soldier. He ran away.");
    james.addReply("map",
      "The #treasure map that leads into the heart of the #dwarven #kingdom.");
    james.addReply("treasure",
      "A big treasure is rumored to be somewhere in this dungeon.");
    james.addReply(Arrays.asList("dwarf", "dwarves", "dwarven", "dwarven kingdom"),
      "They are strong enemies! We're in their #kingdom.");
    james.addReply(Arrays.asList("peter", "tom", "charles"),
      "He was a good soldier and fought bravely.");
    james.addReply(Arrays.asList("kingdom", "kanmararn"),
      "Kanmararn, the legendary kingdom of the #dwarves.");

    final List<ChatAction> actions = new LinkedList<ChatAction>();
    actions.add(new IncreaseXPAction(5000));
    actions.add(new DropInfostringItemAction("map","Henry"));
    actions.add(new SetQuestAndModifyKarmaAction(QUEST_SLOT, "done", 15.0))
    actions.add(new EquipItemAction("steel boots", 1, true));
   
    james.add(ConversationStates.ATTENDING,
        Arrays.asList("map", "henry"),
        new AndCondition(new QuestInStateCondition(QUEST_SLOT, "map"),
                new PlayerHasInfostringItemWithHimCondition("map", "henry")),
        ConversationStates.ATTENDING,
        "The map! Wonderful! Thank you. And here is your reward.",
        new MultipleActions(actions));
   
    james.add(ConversationStates.ATTENDING,
        Arrays.asList("map", "henry"),
        new AndCondition(new QuestInStateCondition(QUEST_SLOT, "map"),
                new NotCondition(new PlayerHasInfostringItemWithHimCondition("map", "henry"))),
        ConversationStates.ATTENDING,
        "Well, where is the map?",
        null);
   
    james.add(ConversationStates.ATTENDING, ConversationPhrases.QUEST_MESSAGES,
        new QuestCompletedCondition(QUEST_SLOT),
        ConversationStates.ATTENDING,
        "Thanks again for bringing me the map!", null);
   
    james.add(ConversationStates.ATTENDING, ConversationPhrases.HELP_MESSAGES,
        new QuestCompletedCondition(QUEST_SLOT),
        ConversationStates.ATTENDING,
        "Thanks again for bringing me the map!", null);
   
    james.add(ConversationStates.ATTENDING, Arrays.asList("map", "henry",
       "group", "one"),
      new QuestCompletedCondition(QUEST_SLOT),
      ConversationStates.ATTENDING,
      "Thanks again for bringing me the map!", null);
  }

  @Override
  public void addToWorld() {
    super.addToWorld();
    fillQuestInfo(
        "Kanmararn Soldiers",
        "Some time ago, Sergeant James started with his crew of four brave soldiers to their adventure of finding a treasure in Kanmararn, the city of dwarves. They didn't return yet.",
        true);
    prepareCowardSoldier();
    prepareCorpses();
    prepareSergeant();
  }
 
  @Override
  public List<String> getHistory(final Player player) {
      final List<String> res = new ArrayList<String>();
      if (!player.hasQuest(QUEST_SLOT)) {
        return res;
      }
      final String questState = player.getQuest(QUEST_SLOT);
      res.add("I met a scared soldier in Kanmararn City. He asked me to find his friends, Peter, Charles, and Tom.");
      if ("rejected".equals(questState)) {
        res.add("I don't want to help Henry.");
        return res;
      }
      if ("start".equals(questState)) {
        return res;
      }
      res.add("Sadly I only found corpses of Peter, Charles, and Tom. Henry was aghast. He gave me a map and an IOU, but didn't say what I should do with them now.");
      if ("map".equals(questState)) {
        return res;
      }
      res.add("I met Sergeant James and gave him the treasure map. He gave me sturdy steel boots in return.");
      if (isCompleted(player)) {
        return res;
      }
      // if things have gone wrong and the quest state didn't match any of the above, debug a bit:
      final List<String> debug = new ArrayList<String>();
      debug.add("Quest state is: " + questState);
      logger.error("History doesn't have a matching quest state for " + questState);
      return debug;
  }

  @Override
  public String getName() {
    return "KanmararnSoldiers";
  }
 
  @Override
  public int getMinLevel() {
    return 40;
  }
}
TOP

Related Classes of games.stendhal.server.maps.quests.KanmararnSoldiers

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.