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