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.script; 14 15 import java.util.Arrays; 16 import java.util.List; 17 import java.util.Random; 18 19 import org.apache.log4j.Logger; 20 21 import games.stendhal.common.Level; 22 import games.stendhal.common.parser.Sentence; 23 import games.stendhal.server.core.config.annotations.ServerModeUtil; 24 import games.stendhal.server.core.engine.SingletonRepository; 25 import games.stendhal.server.core.engine.StendhalRPZone; 26 import games.stendhal.server.core.scripting.ScriptImpl; 27 import games.stendhal.server.core.scripting.ScriptingNPC; 28 import games.stendhal.server.core.scripting.ScriptingSandbox; 29 import games.stendhal.server.entity.item.Item; 30 import games.stendhal.server.entity.item.StackableItem; 31 import games.stendhal.server.entity.npc.ChatAction; 32 import games.stendhal.server.entity.npc.ConversationStates; 33 import games.stendhal.server.entity.npc.EventRaiser; 34 import games.stendhal.server.entity.player.Player; 35 36 /** 37 * Creates a portable NPC who gives ALL players powerful items, increases their 38 * level and makes them admins. This is used on test-systems only. Therefore it 39 * is disabled in default install and you have to use this parameter: 40 * -Dstendhal.testserver=junk as a vm argument. 41 * 42 * As admin uses /script AdminMaker.class to summon her right next to him/her. 43 * Please unload it with /script -unload AdminMaker.class 44 */ 45 46 public class AdminMaker extends ScriptImpl { 47 48 private static Logger logger = Logger.getLogger(AdminMaker.class); 49 private static final String TELE_QUEST_SLOT = "AdminMakerTele"; 50 51 private final List<String> itemsSingle = Arrays.asList("rod of the gm", 52 "golden shield", "golden armor", "golden cloak", 53 "golden helmet", "golden legs", "golden boots", 54 "hunter crossbow"); 55 56 private final List<String> itemsStack = Arrays.asList("money", 57 "greater potion", "greater antidote", "power arrow", 58 "deadly poison"); 59 60 61 protected class UpgradeAction implements ChatAction { 62 xpGain(final Player player)63 private void xpGain(final Player player) { 64 final int level = player.getLevel(); 65 66 // increase level by xlevel per execution 67 int xlevel = 10; 68 69 // Player should at least be min_level after one execution 70 final int min_level = 20; 71 if (level + xlevel < min_level) { 72 xlevel = min_level - level; 73 } 74 75 // Don't give more XP than needed when near/at max 76 if (level + xlevel > Level.maxLevel()) { 77 xlevel = Level.maxLevel() - level; 78 } 79 80 player.addXP(Level.getXP(level + xlevel) - Level.getXP(level)); 81 82 // set the atk and def to half the level (is a good rule of thumb) 83 final int skills = ((Level.getXP(level) + xlevel) / 2); 84 player.setAtkXP(skills); 85 player.setDefXP(skills); 86 player.incAtkXP(); 87 player.incDefXP(); 88 } 89 90 91 equip(final Player player)92 private void equip(final Player player) { 93 94 // Give player all single items from list he/she doesn't have 95 for (final String itemName : itemsSingle) { 96 if (!player.isEquipped(itemName)) { 97 final Item itemObj = sandbox.getItem(itemName); 98 player.equipOrPutOnGround(itemObj); 99 } 100 } 101 102 // Give 5000 of each stack in list, regardless of how many are 103 // already there 104 for (final String itemName : itemsStack) { 105 final Item item = sandbox.getItem(itemName); 106 if (item instanceof StackableItem) { 107 final StackableItem stackableItem = (StackableItem) item; 108 stackableItem.setQuantity(5000); 109 player.equipToInventoryOnly(stackableItem); 110 } 111 } 112 // turn on their keyring for them 113 player.setFeature("keyring", true); 114 } 115 admin(final Player player)116 private void admin(final Player player) { 117 if (player.getAdminLevel() == 0) { 118 // can't use destroy/summon/alter/script 119 player.setAdminLevel(600); 120 player.update(); 121 player.notifyWorldAboutChanges(); 122 } 123 } 124 125 @Override fire(final Player player, final Sentence sentence, final EventRaiser raiser)126 public void fire(final Player player, final Sentence sentence, final EventRaiser raiser) { 127 raiser.say("I will give you some items, and adjust your level and skills. Also, your keyring is enabled."); 128 xpGain(player); 129 equip(player); 130 admin(player); 131 } 132 } 133 134 protected class TeleportAction implements ChatAction { 135 private class Destination { 136 private final String zone; 137 private final int x; 138 private final int y; 139 Destination(final String zone, final int x, final int y)140 Destination(final String zone, final int x, final int y) { 141 this.zone = zone; 142 this.x = x; 143 this.y = y; 144 } 145 } 146 147 private final List<Destination> DESTINATIONS = Arrays.asList( 148 new Destination("0_nalwor_city", 88, 85), 149 new Destination("-1_nalwor_drows_tunnel_n", 58, 44), 150 new Destination("0_ados_city", 30, 57), 151 new Destination("0_orril_forest_e", 107, 7), 152 new Destination("0_ados_mountain_n2_w2", 10, 100), 153 new Destination("0_semos_mountain_n2_e2", 86, 71), 154 new Destination("-2_orril_dungeon", 106, 21), 155 new Destination("-2_orril_lich_palace", 67, 118), 156 new Destination("-2_orril_dwarf_mine", 50, 40), 157 new Destination("-1_semos_mine_nw", 22, 75), 158 new Destination("-6_kanmararn_city", 33, 52), 159 new Destination("-2_ados_outside_nw", 28, 4), 160 new Destination("-2_kotoch_entrance", 20, 111), 161 new Destination("1_kikareukin_cave", 18, 97), 162 new Destination("0_kalavan_city", 64, 13), 163 new Destination("0_kirdneh_city", 63, 26), 164 new Destination("0_fado_city", 30, 20), 165 new Destination("-1_fado_great_cave_e3", 13, 100), 166 new Destination("-1_fado_great_cave_w2", 90, 57), 167 new Destination("0_athor_island", 77, 73), 168 new Destination("5_kikareukin_cave", 31, 100), 169 new Destination("-2_semos_mine_e2", 4, 5), 170 new Destination("0_amazon_island_nw", 30, 30), 171 new Destination("int_mithrilbourgh_stores", 6, 5) 172 ); 173 174 randomTeleport(final Player player)175 private boolean randomTeleport(final Player player) { 176 // Destination selection: random for first, then go in order 177 // todo: maybe mix in a second kind of random like bunny/santa? 178 179 // pick a Destination 180 int i; 181 if (player.hasQuest(TELE_QUEST_SLOT)) { 182 i = Integer.parseInt(player.getQuest(TELE_QUEST_SLOT)); 183 } else { 184 i = new Random().nextInt(DESTINATIONS.size()); 185 } 186 i++; 187 if (i >= DESTINATIONS.size()) { 188 i = 0; 189 } 190 player.setQuest(TELE_QUEST_SLOT, "" + i); 191 final Destination picked = DESTINATIONS.get(i); 192 193 // Teleport 194 final StendhalRPZone zone = SingletonRepository.getRPWorld().getZone(picked.zone); 195 if (!player.teleport(zone, picked.x, picked.y, null, player)) { 196 logger.error("AdminMaker random teleport failed, " 197 + picked.zone + " " + picked.x + " " + picked.y); 198 return false; 199 } 200 return true; 201 } 202 203 204 @Override fire(final Player player, final Sentence sentence, final EventRaiser raiser)205 public void fire(final Player player, final Sentence sentence, final EventRaiser raiser) { 206 207 // before we send the player off into the unknown give a marked 208 // scroll 209 final Item markedScroll = sandbox.getItem("marked scroll"); 210 markedScroll.setInfoString(player.getID().getZoneID() + " " 211 + player.getX() + " " + player.getY()); 212 markedScroll.setBoundTo(player.getName()); 213 214 if (player.equipToInventoryOnly(markedScroll)) { 215 // Teleport 216 if (randomTeleport(player)) { 217 // todo: priv msg doesn't work 218 player.sendPrivateText(player.getTitle() 219 + " use the scroll to come back here. Use /teleport <playername> <zonename> <x> <y> to beam to a different place."); 220 } else { 221 raiser.say("oops, looks like you found a bug."); 222 } 223 } else { 224 raiser.say("Ask me again when you have room for a scroll."); 225 } 226 227 } 228 } 229 230 @Override load(final Player admin, final List<String> args, final ScriptingSandbox sandbox)231 public void load(final Player admin, final List<String> args, final ScriptingSandbox sandbox) { 232 super.load(admin, args, sandbox); 233 234 // Require parameter -Dstendhal.testserver=junk 235 if (!ServerModeUtil.isTestServer()) { 236 final String msg = "Server must be started with this vm parameter: -Dstendhal.testserver=junk"; 237 if (admin != null) { 238 admin.sendPrivateText(msg); 239 logger.warn("AdminMaker - " + msg + " . Executed by " 240 + admin.getName()); 241 } 242 return; 243 } 244 245 246 247 // create npc 248 ScriptingNPC npc; 249 npc = new ScriptingNPC("Admin Maker"); 250 npc.setEntityClass("tavernbarmaidnpc"); 251 252 // Place NPC in int_admin_playground on server start 253 final String myZone = "0_semos_city"; 254 sandbox.setZone(myZone); 255 int x = 32; 256 int y = 16; 257 258 // if this script is executed by an admin, Admin Maker will be placed 259 // next to 260 // him/her. 261 if (admin != null) { 262 sandbox.setZone(sandbox.getZone(admin)); 263 x = admin.getX() + 1; 264 y = admin.getY(); 265 } 266 267 // Set zone and position 268 npc.setPosition(x, y); 269 sandbox.add(npc); 270 271 // Create Dialog 272 npc.behave("greet", "Hi, how can i #help you?"); 273 npc.behave("help", 274 "Perhaps you would like a free power #upgrade and maybe a #random destination?"); 275 npc.addGoodbye(); 276 npc.add(ConversationStates.ATTENDING, "upgrade", null, 277 ConversationStates.ATTENDING, null, new UpgradeAction()); 278 npc.add(ConversationStates.ATTENDING, "random", null, 279 ConversationStates.ATTENDING, null, new TeleportAction()); 280 281 } 282 283 } 284