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