1 /* $Id$ */
2 /***************************************************************************
3  *                   (C) Copyright 2003-2010 - Stendhal                    *
4  ***************************************************************************
5  ***************************************************************************
6  *                                                                         *
7  *   This program is free software; you can redistribute it and/or modify  *
8  *   it under the terms of the GNU General Public License as published by  *
9  *   the Free Software Foundation; either version 2 of the License, or     *
10  *   (at your option) any later version.                                   *
11  *                                                                         *
12  ***************************************************************************/
13 package games.stendhal.server.entity.mapstuff.useable;
14 
15 import games.stendhal.common.Rand;
16 import games.stendhal.common.constants.SoundLayer;
17 import games.stendhal.common.grammar.Grammar;
18 import games.stendhal.server.core.engine.SingletonRepository;
19 import games.stendhal.server.entity.item.Item;
20 import games.stendhal.server.entity.player.Player;
21 import games.stendhal.server.events.SoundEvent;
22 import marauroa.common.game.RPClass;
23 
24 /**
25  * A water spring source is a spot where a player can fill an empty flask with spring water.
26  *
27  * Filling an empty flask takes 10 seconds + randomized 4 seconds; during this time, the player keep standing next to
28  * the water spring.
29  *
30  * @author Vanessa Julius (based on WellSource by kymara)
31  *
32  */
33 public class WaterSpringSource extends PlayerActivityEntity {
34 	/**
35 	 * The reward
36 	 */
37 	private static final String[] items = { "water" };
38 
39 	/**
40 	 * The chance that filling flask is successful.
41 	 */
42 	private static final double FINDING_PROBABILITY = 0.50;
43 
44 	/**
45 	 * How long it takes to fill the bottle (in seconds).
46 	 */
47 	private static final int DURATION = 10;
48 
49 	/**
50 	 * Sound effects
51 	 */
52 	private final String startSound = "liquid-fill-01";
53 	private final String successSound = "cork-pop-1";
54 	private final String failSound = "glass-break-2";
55 	private final int SOUND_RADIUS = 20;
56 
57 	/**
58 	 * Create a water spring source.
59 	 */
WaterSpringSource()60 	public WaterSpringSource() {
61 		put("class", "source");
62 		put("name", "water_source");
63 		setMenu("Fill|Use");
64 		setDescription("You see some bubbles in the water. Seems like you found a spring.");
65 		setResistance(0);
66 	}
67 
68 	/**
69 	 * source name.
70 	 */
71 	@Override
getName()72 	public String getName() {
73 		return("water spring");
74 	}
75 
76 	//
77 	// WaterSpringSource
78 	//
79 
generateRPClass()80 	public static void generateRPClass() {
81 		final RPClass rpclass = new RPClass("water_source");
82 		rpclass.isA("entity");
83 	}
84 
85 	//
86 	// PlayerActivityEntity
87 	//
88 
89 	/**
90 	 * Get the time it takes to perform this activity.
91 	 *
92 	 * @return The time to perform the activity (in seconds).
93 	 */
94 	@Override
getDuration()95 	protected int getDuration() {
96 		return DURATION + Rand.rand(5);
97 	}
98 
99 	/**
100 	 * Decides if the activity can be done.
101 	 *
102 	 * @return <code>true</code> if successful.
103 	 */
104 	@Override
isPrepared(final Player player)105 	protected boolean isPrepared(final Player player) {
106         /*
107         * The player can fill an empty flask at the spring.
108         * Check they have it before they can start filling it up.
109 		*/
110 		if (player.isEquipped("flask")) {
111 			return true;
112 		} else {
113 			player.sendPrivateText("You need a flask to fill some water up.");
114 			return false;
115 		}
116 	}
117 
118 	/**
119 	 * Decides if the activity was successful.
120 	 *
121 	 * @return <code>true</code> if successful.
122 	 */
123 	@Override
isSuccessful(final Player player)124 	protected boolean isSuccessful(final Player player) {
125 		final int random = Rand.roll1D100();
126         /*
127         * Use some karma to help decide if the outcome is successful
128         * We want to use up quite a bit karma at once, so scale it after
129 		*/
130 		double karma = player.useKarma(FINDING_PROBABILITY*10);
131 
132 		// if player karma is > 0 it will always return at least 20% of FINDING_PROBABILITY*10, or karma, whichever is smaller
133 		// so we can safely say if the karma returned is <= 0, the player had <= 0 karma.
134 		// so we'll penalise these stronger
135 		if (karma <= 0) {
136 			karma = karma - FINDING_PROBABILITY*5;
137 		}
138 		karma = karma / 10;
139 		// right hand side could be negative, if karma was negative but thats ok.
140 		return random <= (FINDING_PROBABILITY + karma) * 100;
141 	}
142 
143 	/**
144 	 * Called when the activity has finished.
145 	 *
146 	 * @param player
147 	 *            The player that did the activity.
148 	 * @param successful
149 	 *            If the activity was successful.
150 	 */
151 	@Override
onFinished(final Player player, final boolean successful)152 	protected void onFinished(final Player player, final boolean successful) {
153 		if (successful) {
154 			final String itemName = items[Rand.rand(items.length)];
155 			final Item item = SingletonRepository.getEntityManager().getItem(itemName);
156 			int amount = 1;
157 			if (itemName.equals("water"))
158 					 {
159 				/*
160 				 * Bound powerful items.
161 				 */
162 				item.setBoundTo(player.getName());
163 
164 			}
165 
166             this.addEvent(new SoundEvent(successSound, SOUND_RADIUS, 100, SoundLayer.AMBIENT_SOUND));
167     		this.notifyWorldAboutChanges();
168 
169 
170 			player.equipOrPutOnGround(item);
171 			player.sendPrivateText("You were lucky and filled "
172 					+ Grammar.quantityplnoun(amount, itemName, "a")+ ".");
173 
174 		} else {
175             this.addEvent(new SoundEvent(failSound, SOUND_RADIUS, 100, SoundLayer.AMBIENT_SOUND));
176     		this.notifyWorldAboutChanges();
177 
178 			player.sendPrivateText("Oh no! You spilled the water and let the flask fall into it. Now it's broken.");
179 		}
180 		notifyWorldAboutChanges();
181 	}
182 
183 	/**
184 	 * Called when the activity has started.
185 	 *
186 	 * @param player
187 	 *            The player starting the activity.
188 	 */
189 	@Override
onStarted(final Player player)190 	protected void onStarted(final Player player) {
191 	    // Play a nice sound effect
192         addEvent(new SoundEvent(startSound, SOUND_RADIUS, 100, SoundLayer.AMBIENT_SOUND));
193         notifyWorldAboutChanges();
194 
195 		// remove flask from player as they try to fill it.
196 		player.drop("flask");
197 		player.sendPrivateText("You started to fill fresh spring water into an empty flask. It will hopefully not slip out of your hand!");
198 	}
199 }
200