Compare commits

...
Sign in to create a new pull request.

23 commits

Author SHA1 Message Date
Hendrik Brummermann
e91e9caf2c deleted unused file 2010-07-26 17:50:25 +00:00
Hendrik Brummermann
19282a1ae3 use "an item" instead of "1 item" to be consistent with SayRequiredItemAction 2010-07-24 19:45:27 +00:00
Hendrik Brummermann
9480757c31 don't double sign 2010-07-24 14:40:25 +00:00
Hendrik Brummermann
a9572bf66d don't let the BuyerAdder add a handler for "offer" for NPCs that already defined one (fixes #3033411) 2010-07-23 22:23:59 +00:00
Hendrik Brummermann
123e7de072 create diff of stendhal-sound-0.xx.jar, too 2010-07-23 21:59:22 +00:00
Hendrik Brummermann
6578c97c76 backported radius change of music by storyteller 2010-07-23 21:42:53 +00:00
Katie Russell
12ec6c482a remove rift cloak from this version as it is not ready 2010-07-23 18:33:47 +00:00
Katie Russell
eb40b80c84 backport: write to file not server.log 2010-07-23 06:39:05 +00:00
Katie Russell
e411ce1278 backport changes to the wizards tower:
- messages on successful use of portal
- messaging areas to help at first stage
- removed nonexisting sound
- added the_magical_tower music and changed some volumes
2010-07-23 06:37:12 +00:00
Katie Russell
b38131c50d backport send private message action 2010-07-23 06:34:13 +00:00
Katie Russell
db32a39137 backport removal of special items which are not used yet in this release 2010-07-23 06:33:04 +00:00
Katie Russell
120c054159 Backport mkvii's changes :
-increased the spark of the hexagram
-removed graphic bugs
2010-07-23 06:27:54 +00:00
Katie Russell
ead6344cc2 fix extra tag 2010-07-23 06:24:02 +00:00
Katie Russell
6700e8c209 remove ice scroll and blank scroll, they are not used in this release and so they shouldn't appear on items page. also i do not think they should be in 'documents' anyway. 2010-07-23 06:23:43 +00:00
Hendrik Brummermann
cfe6adc23e fixed client side of map based feature for karma indicator 2010-07-22 19:36:52 +00:00
Hendrik Brummermann
3be735d401 updated marauroa 2010-07-22 19:24:14 +00:00
Katie Russell
ddf07a1cdd Backport kiheru's fix for [3031671] [Stendhal] zone/area entry message before welcome message 2010-07-22 18:56:58 +00:00
Hendrik Brummermann
7a6dc30010 removed code for experimental achievements 2010-07-22 18:54:36 +00:00
Hendrik Brummermann
855a566739 removed event code for experimental achievements 2010-07-22 18:53:48 +00:00
Hendrik Brummermann
64d9e88e94 removed database code for experimental achievements 2010-07-22 18:53:27 +00:00
Katie Russell
54d428031d backport kiheru's fix for [3031689] [Stendhal] running with keyboard floods server-Windows 2010-07-22 18:51:24 +00:00
Hendrik Brummermann
cd6c2bdd57 fixed error message about non existing !features slot on newly created accoutns 2010-07-22 18:07:14 +00:00
Hendrik Brummermann
80546f82be updated version number 2010-07-21 21:07:39 +00:00
45 changed files with 329 additions and 910 deletions

View file

@ -73,7 +73,7 @@ version_server = http://arianne.sourceforge.net/stendhal.version
# current version of stendhal
version.old = 0.85
version = 0.85.5
version = 0.86
# javac options
javac.deprecation = true

View file

@ -503,11 +503,6 @@
<include name="**/*.jar"/>
</fileset>
</signjar>
<signjar alias="stendhal" keystore="keystore.ks" storepass="${keystore.password}">
<fileset dir="${build_sign}">
<include name="**/*.jar"/>
</fileset>
</signjar>
</target>
<target name="dist" depends="clean, dist_binary, dist_source" description="Creates all the packages needed for a Stendhal release"/>

View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<achievements xmlns="stendhal" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="stendhal ../achievements.xsd ">
<achievement>
<condition>
</condition>
</achievement>
</achievements>

View file

@ -317,17 +317,4 @@
</equipable>
</item>
<item name="rift cloak">
<type class="cloak" subclass="rift_cloak" tileid="-1"/>
<description>You see a rift cloak. Almost useless in the battle, but saves your life when you enter a magical rift.</description>
<implementation class-name="games.stendhal.server.entity.item.Item"/> <attributes>
<def value="1"/>
</attributes>
<weight value="2.0"/>
<value value="10000"/>
<equipable>
<slot name="bag"/>
<slot name="cloak"/>
</equipable>
</item>
</items>

View file

@ -108,35 +108,4 @@
</equipable>
</item>
<item name="scroll">
<type class="documents" subclass="scroll" tileid="-1"/>
<description>You see a rolled up scroll.</description>
<implementation class-name="games.stendhal.server.entity.item.Item"/>
<attributes>
<quantity value="1"/>
</attributes>
<weight value="0.01"/>
<value value="1"/>
<equipable>
<slot name="bag"/>
<slot name="lhand"/>
<slot name="rhand"/>
</equipable>
</item>
<item name="ice scroll">
<type class="documents" subclass="ice_scroll" tileid="-1"/>
<description>You see a scroll, circled by ice crystals. You can feel its cold aura.</description>
<implementation class-name="games.stendhal.server.entity.item.Item"/>
<attributes>
<quantity value="1"/>
</attributes>
<weight value="0.01"/>
<value value="1"/>
<equipable>
<slot name="bag"/>
<slot name="lhand"/>
<slot name="rhand"/>
</equipable>
</item>
</items>

View file

@ -38,11 +38,11 @@
<entity x="77" y="123">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.PeriodicAmbientSoundSource">
<parameter name="sound">water-3</parameter>
<parameter name="sound">water-2</parameter>
<parameter name="min">1</parameter>
<parameter name="max">1</parameter>
<parameter name="radius">11</parameter>
<parameter name="volume">80</parameter>
<parameter name="volume">40</parameter>
</implementation>
</entity>
@ -221,6 +221,14 @@
<destination zone="int_semos_wizards_tower_basement" ref="wizardstower_exit" />
</portal>
<entity x="77" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">come_to_rest</parameter>
<parameter name="radius">13</parameter>
<parameter name="volume">100</parameter>
</implementation>
</entity>
<entity x="78" y="28">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">mystical_aura</parameter>
@ -229,14 +237,6 @@
</implementation>
</entity>
<entity x="77" y="2">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">come_to_rest</parameter>
<parameter name="radius">13</parameter>
<parameter name="volume">100</parameter>
</implementation>
</entity>
<entity x="65" y="6">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.PeriodicAmbientSoundSource">
<parameter name="sound">woodpecker-1</parameter>
@ -251,6 +251,14 @@
<!-- Interiors of the wizards tower -->
<zone name="int_semos_wizards_tower_basement" file="interiors/semos/wizards_tower_basement.tmx">
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.WizardsGuardStatueNPC" />
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<portal x="15" y="29" ref="wizardstower_exit">
<destination zone="0_semos_mountain_n_w2" ref="wizardstower_entrance" />
</portal>
@ -263,6 +271,14 @@
<zone name="int_semos_wizards_tower_1" file="interiors/semos/wizards_tower_1.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.FirstFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -270,6 +286,22 @@
</implementation>
</entity>
<entity x="14" y="6">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="width">3</parameter>
<parameter name="height">2</parameter>
<parameter name="enterMessage">You step onto a sparkling corner of the hexagram, this must be what Zekiel the guardian was talking about.</parameter>
</implementation>
</entity>
<entity x="25" y="14">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="width">2</parameter>
<parameter name="height">3</parameter>
<parameter name="enterMessage">This looks like a creature matching the theme of Malleus ... perhaps this is the one to select.</parameter>
</implementation>
</entity>
<portal x="15" y="15" ref="first_floor_exit">
<destination zone="int_semos_wizards_tower_basement" ref="basement_teleport" />
</portal>
@ -286,8 +318,8 @@
<destination zone="int_semos_wizards_tower_1" ref="choice_floor_1" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","first_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Malleus. Now use the candle at the shimmering spot of the hexagram."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "second_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Malleus. Now use the candle at the shimmering spot of the hexagram.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Malleus. Now use the candle at the shimmering spot of the hexagram.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "second_step")])</parameter>
</implementation>
</portal>
@ -314,6 +346,14 @@
<zone name="int_semos_wizards_tower_2" file="interiors/semos/wizards_tower_2.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.SecondFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -345,8 +385,8 @@
<destination zone="int_semos_wizards_tower_2" ref="choice_floor_2" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","second_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Jaer. Now use the candle at the next shimmering spot of the hexagram."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "third_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Jaer. Now use the candle at the next shimmering spot of the hexagram.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Jaer. Now use the candle at the next shimmering spot of the hexagram.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "third_step")])</parameter>
</implementation>
</portal>
@ -369,6 +409,14 @@
<zone name="int_semos_wizards_tower_3" file="interiors/semos/wizards_tower_3.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.ThirdFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -404,8 +452,8 @@
<destination zone="int_semos_wizards_tower_3" ref="choice_floor_3" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","third_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Ravashack. You have almost done the half of the test. Search the next shimmering spot of the hexagram."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "fourth_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Ravashack. You have almost done the half of the test. Search the next shimmering spot of the hexagram.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Ravashack. You have almost done the half of the test. Search the next shimmering spot of the hexagram.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "fourth_step")])</parameter>
</implementation>
</portal>
@ -424,6 +472,14 @@
<zone name="int_semos_wizards_tower_4" file="interiors/semos/wizards_tower_4.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.FourthFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -451,8 +507,8 @@
<destination zone="int_semos_wizards_tower_4" ref="choice_floor_4" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","fourth_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Cassandra. One triangle is ready. Use the candle at shimmering spot of the other triangle."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "fifth_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Cassandra. One triangle is ready. Use the candle at the shimmering spot of the other triangle.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Cassandra. One triangle is ready. Use the candle at the shimmering spot of the other triangle.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "fifth_step")])</parameter>
</implementation>
</portal>
@ -479,6 +535,14 @@
<zone name="int_semos_wizards_tower_5" file="interiors/semos/wizards_tower_5.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.FifthFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -514,8 +578,8 @@
<destination zone="int_semos_wizards_tower_5" ref="choice_floor_5" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","fifth_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Silvanus. The next shimmering spot awaits you and the last step of the test too."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "sixth_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Silvanus. The next shimmering spot awaits you and the last step of the test too.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Silvanus. The next shimmering spot awaits you and the last step of the test too.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "sixth_step")])</parameter>
</implementation>
</portal>
@ -534,6 +598,14 @@
<zone name="int_semos_wizards_tower_6" file="interiors/semos/wizards_tower_6.tmx">
<configurator class-name="games.stendhal.server.core.config.zone.NoTeleportIn" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.SixthFloorCreatures"/>
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<entity x="0" y="0">
<implementation class-name="games.stendhal.server.entity.mapstuff.area.MessagingArea">
<parameter name="coversZone">true</parameter>
@ -557,8 +629,8 @@
<destination zone="int_semos_wizards_tower_6" ref="choice_floor_6" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new QuestInStateCondition("zekiels_practical_test","sixth_step")</parameter>
<parameter name="rejected">Zekiel the guardian: "You have chosen the correct one of Elana. Complete the hexagram and I will wait for you at the next stage. Please talk to me there to finish the quest."</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "last_step")])</parameter>
<parameter name="rejected">Zekiel the guardian: 'You have chosen the correct one of Elana. Complete the hexagram and I will wait for you at the next stage. Please talk to me there to finish the quest.'</parameter>
<parameter name="action">new MultipleActions([new SendPrivateMessageAction("Zekiel the guardian: 'You have chosen the correct one of Elana. Complete the hexagram and I will wait for you at the next stage. Please talk to me there to finish the quest.'"), new EquipItemAction("candle"), new SetQuestAction("zekiels_practical_test", "last_step")])</parameter>
</implementation>
</portal>
@ -588,6 +660,14 @@
<!-- Interiors of the wizards tower -->
<zone name="int_semos_wizards_tower_7" file="interiors/semos/wizards_tower_7.tmx">
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.WizardsGuardStatueSpireNPC" />
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">the_magical_tower</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<portal x="23" y="10" ref="portal_from_sixth_floor">
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination"/>
</portal>
@ -604,6 +684,14 @@
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.BlueIceSorceressNPC" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.OrientalAirWizardNPC" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.GreenNatureWizardNPC" />
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">mystical_aura</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<portal x="21" y="7" ref="portal_from_spire_2">
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination"/>
</portal>
@ -654,6 +742,14 @@
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.BlackDeathWizardNPC" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.WhiteLifeSorceressNPC" />
<configurator class-name="games.stendhal.server.maps.semos.wizardstower.BlueArchmageNPC" />
<entity x="15" y="15">
<implementation class-name="games.stendhal.server.entity.mapstuff.sound.BackgroundMusicSource">
<parameter name="sound">mystical_aura</parameter>
<parameter name="volume">120</parameter>
</implementation>
</entity>
<portal x="21" y="6" ref="portal_from_spire_1">
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination"/>
</portal>

Binary file not shown.

View file

@ -75,6 +75,14 @@
<arg value="${build-archive}/lib/stendhal-music-data-${version.old}.jar" />
<arg value="${build}/lib/stendhal-music-data-${version}.jar" />
</java>
<java jar="libs/jardiff.jar" fork="true">
<arg value="-nonminimal" />
<arg value="-creatediff" />
<arg value="-output" />
<arg value="${build}/lib/stendhal-sound-data-diff-${version.old}-${version}.jar" />
<arg value="${build-archive}/lib/stendhal-sound-data-${version.old}.jar" />
<arg value="${build}/lib/stendhal-sound-data-${version}.jar" />
</java>
<!-- TODO maraurora.jar-->
</target>
@ -90,11 +98,6 @@
<include name="*-diff*.jar"/>
</fileset>
</signjar>
<signjar alias="stendhal" keystore="keystore.ks" storepass="${keystore.password}">
<fileset dir="${lib}">
<include name="*-diff*.jar"/>
</fileset>
</signjar>
</target>
<target name="upload-diff">

View file

@ -1,3 +1,3 @@
set STENDHAL_VERSION=0.85.5
set STENDHAL_VERSION=0.86
set LOCALCLASSPATH=.;data\script;data\conf;stendhal-server-%STENDHAL_VERSION%.jar;marauroa.jar;mysql-connector.jar;log4j.jar;commons-lang.jar;h2.jar
java -Xmx400m -cp "%LOCALCLASSPATH%" marauroa.server.marauroad -c server.ini -l

View file

@ -1,5 +1,5 @@
#!/bin/sh
STENDHAL_VERSION="0.85.5"
STENDHAL_VERSION="0.86"
LOCALCLASSPATH=.:data/script/:data/conf/:stendhal-server-$STENDHAL_VERSION.jar:marauroa.jar:mysql-connector.jar:log4j.jar:commons-lang.jar:h2.jar

View file

@ -467,6 +467,15 @@ public class StendhalClient extends ClientFramework {
*/
idx = directions.indexOf(dir);
if (idx != -1) {
/*
* Already highest priority? Don't send to server.
*/
if (idx == (directions.size() - 1)) {
logger.debug("Ignoring same direction: " + dir);
return;
}
/*
* Move to end
*/

View file

@ -2,6 +2,7 @@ package games.stendhal.client;
import games.stendhal.client.gui.bag.BagPanelControler;
import games.stendhal.client.gui.buddies.BuddyPanelControler;
import games.stendhal.client.gui.stats.KarmaIndicator;
import games.stendhal.client.gui.stats.StatsPanelController;
import java.beans.PropertyChangeListener;
@ -23,7 +24,8 @@ public class UserController implements ObjectChangeListener {
pcs.addPropertyChangeListener("!buddy", BuddyPanelControler.get());
pcs.addPropertyChangeListener("buddies", BuddyPanelControler.getMapBasedBuddyPropertyChangeListener());
pcs.addPropertyChangeListener("bag", BagPanelControler.get());
pcs.addPropertyChangeListener("features", KarmaIndicator.get());
StatsPanelController stats = StatsPanelController.get();
stats.registerListeners(pcs);
}

View file

@ -1,7 +1,5 @@
package games.stendhal.client.gui.stats;
import games.stendhal.client.StendhalClient;
import games.stendhal.client.listener.FeatureChangeListener;
import games.stendhal.client.sprite.Sprite;
import games.stendhal.client.sprite.SpriteStore;
@ -9,6 +7,9 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
@ -16,9 +17,11 @@ import javax.swing.SwingUtilities;
/**
* A bar indicator component for karma.
*/
public class KarmaIndicator extends JComponent implements FeatureChangeListener {
public class KarmaIndicator extends JComponent implements PropertyChangeListener {
private static final long serialVersionUID = 3462088641737184898L;
private static KarmaIndicator instance;
/**
* Scaling factor for interpreting karma to bar length. Smaller means
* smaller change in karma bar for a karma change.
@ -34,15 +37,24 @@ public class KarmaIndicator extends JComponent implements FeatureChangeListener
* Create a new karma indicator.
*/
public KarmaIndicator() {
instance = this;
setVisible(false);
final SpriteStore store = SpriteStore.get();
image = store.getSprite(IMAGE_FILE_NAME);
// We don't draw the background
setOpaque(false);
StendhalClient.get().addFeatureChangeListener(this);
}
/**
* gets the instance
*
* @return KarmaIndicator
*/
public static KarmaIndicator get() {
return instance;
}
/**
* Set the karma value.
*
@ -90,11 +102,15 @@ public class KarmaIndicator extends JComponent implements FeatureChangeListener
image.draw(g, insets.left, insets.top);
}
/**
* disables the karma indicator.
*/
public void featureDisabled(String name) {
if (name.equals("karma_indicator")) {
public void propertyChange(PropertyChangeEvent evt) {
if (evt == null) {
return;
}
// disable
Map<?, ?> oldMap = (Map<?, ?>) evt.getOldValue();
if ((oldMap != null) && oldMap.containsKey("karma_indicator")) {
// Feature changes are triggered from outside the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
@ -102,13 +118,10 @@ public class KarmaIndicator extends JComponent implements FeatureChangeListener
}
});
}
}
/**
* enables the karma indicator.
*/
public void featureEnabled(String name, String value) {
if (name.equals("karma_indicator")) {
// enable
Map<?, ?> newMap = (Map<?, ?>) evt.getNewValue();
if ((newMap != null) && newMap.containsKey("karma_indicator")) {
// Feature changes are triggered from outside the EDT.
SwingUtilities.invokeLater(new Runnable() {
public void run() {

View file

@ -10,7 +10,7 @@ package games.stendhal.client.update;
public class Version {
/** Version Number. */
public static final String VERSION = "0.85.5";
public static final String VERSION = "0.86";
/**
* Extract the specified number of parts from a version-string.

View file

@ -25,7 +25,7 @@ public interface Debug {
/** server version. */
// Note: This line is updated by build.xml using a regexp so be sure to adjust it in case you modify this line.
String VERSION = "0.85.5";
String VERSION = "0.86";
/**

View file

@ -234,7 +234,7 @@ public class GenerateINI {
out.println();
out.println("server_typeGame=" + gameName);
out.println("server_name=" + gameName + " Marauroa server");
out.println("server_version=0.85.5");
out.println("server_version=0.86");
out.println("server_contact=https://sourceforge.net/tracker/?atid=514826&group_id=66537&func=browse");
out.println();
out.println("# Extensions configured on the server. Enable at will.");

View file

@ -2,7 +2,6 @@ package games.stendhal.server.core.engine;
import games.stendhal.server.core.events.LoginNotifier;
import games.stendhal.server.core.events.TurnNotifier;
import games.stendhal.server.core.events.achievements.AchievementNotifier;
import games.stendhal.server.core.rp.StendhalQuestSystem;
import games.stendhal.server.core.rp.guilds.GuildList;
import games.stendhal.server.core.rp.guilds.GuildPermissionList;
@ -147,13 +146,6 @@ public class SingletonRepository {
return AthorFerry.get();
}
/**
* @return the AchievementNotifier instance
*/
public static AchievementNotifier getAchievementNotifier() {
return AchievementNotifier.get();
}
/**
* @return the actual EntityManager instance
*/

View file

@ -1,6 +1,5 @@
package games.stendhal.server.core.engine;
import games.stendhal.server.core.engine.db.AchievementDAO;
import games.stendhal.server.core.engine.db.CidDAO;
import games.stendhal.server.core.engine.db.PostmanDAO;
import games.stendhal.server.core.engine.db.StendhalBuddyDAO;
@ -59,6 +58,5 @@ public class StendhalPlayerDatabase {
DAORegister.get().register(StendhalKillLogDAO.class, new StendhalKillLogDAO ());
DAORegister.get().register(StendhalNPCDAO.class, new StendhalNPCDAO());
DAORegister.get().register(StendhalWebsiteDAO.class, new StendhalWebsiteDAO());
DAORegister.get().register(AchievementDAO.class, new AchievementDAO());
}
}

View file

@ -141,7 +141,6 @@ public class StendhalRPWorld extends RPWorld {
loader.load();
validatePortals();
SingletonRepository.getAchievementNotifier().initialize();
SingletonRepository.getGagManager();
SingletonRepository.getJail();
} catch (final Exception e) {

View file

@ -1,97 +0,0 @@
package games.stendhal.server.core.engine.db;
import games.stendhal.server.core.events.achievements.Category;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import marauroa.server.db.DBTransaction;
/**
* DAO to handle achievements for the stendhal website
* @author madmetzger
*
*/
public class AchievementDAO {
/**
* logs a reached achievement into the database
*
* @param achievementId
* @param playerName
* @param transaction
* @throws SQLException
*/
public void saveReachedAchievement(Integer achievementId, String playerName, DBTransaction transaction) throws SQLException {
String query = "INSERT INTO reached_achievement " +
"(charname, achievement_id) VALUES" +
"('[charname]','[achievement_id]');";
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("charname", playerName);
parameters.put("achievement_id", achievementId);
transaction.execute(query, parameters);
}
/**
* creates a new achievement
*
* @param identifier
* @param title
* @param category
* @param transaction
* @return
* @throws SQLException
*/
public int saveAchievement(String identifier, String title, Category category, DBTransaction transaction) throws SQLException {
int achievementId = 0;
String query = "INSERT INTO achievement " +
"(identifier, title, category) VALUES " +
"('[identifier]','[title]','[category]')";
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("identifier", identifier);
parameters.put("title", title);
parameters.put("category", category.toString());
transaction.execute(query, parameters);
achievementId = transaction.getLastInsertId("achievement", "id");
return achievementId;
}
/**
* loads a map from achievement identifier to database serial
* @param transaction
* @return map with key identifier string and value database id
* @throws SQLException
*/
public Map<String, Integer> loadIdentifierIdPairs(DBTransaction transaction) throws SQLException {
Map<String, Integer> map = new HashMap<String, Integer>();
String query = "SELECT identifier, id FROM achievement;";
ResultSet set = transaction.query(query, new HashMap<String, Object>());
while (set.next()) {
String identifier = set.getString("identifier");
Integer id = set.getInt("id");
map.put(identifier, id);
};
return map;
}
/**
* @param playerName
* @return set identifiers of achievements reached by playerName
* @throws SQLException
*/
public Set<String> loadAllReachedAchievementsOfPlayer(String playerName, DBTransaction transaction) throws SQLException {
Map<String, Object> params = new HashMap<String, Object>();
params.put("playername", playerName);
String query = "SELECT identifier FROM achievement a JOIN reached_achievement ra ON ra.achievement_id = a.id WHERE ra.charname = '[playername]';";
ResultSet resultSet = transaction.query(query, params);
Set<String> identifiers = new HashSet<String>();
while(resultSet.next()) {
identifiers.add(resultSet.getString(1));
}
return identifiers;
}
}

View file

@ -1,38 +0,0 @@
package games.stendhal.server.core.engine.dbcommand;
import games.stendhal.server.core.engine.db.AchievementDAO;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
import marauroa.server.db.DBTransaction;
import marauroa.server.db.command.AbstractDBCommand;
import marauroa.server.game.db.DAORegister;
/**
* reads all achievement identifiers and the corresponding ids from the database
*
* @author madmetzger
*/
public class ReadAchievementIdentifierToIdMap extends AbstractDBCommand {
private Map<String, Integer> identifierToIdMap;
@Override
public void execute(DBTransaction transaction) throws SQLException,
IOException {
setIdentifierToIdMap(DAORegister.get().get(AchievementDAO.class).loadIdentifierIdPairs(transaction));
}
private void setIdentifierToIdMap(Map<String, Integer> identifierToIdMap) {
this.identifierToIdMap = identifierToIdMap;
}
/**
* @return map from identifier for achievement to its database id
*/
public Map<String, Integer> getIdentifierToIdMap() {
return identifierToIdMap;
}
}

View file

@ -1,41 +0,0 @@
package games.stendhal.server.core.engine.dbcommand;
import games.stendhal.server.core.engine.db.AchievementDAO;
import games.stendhal.server.entity.player.Player;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Set;
import marauroa.server.db.DBTransaction;
import marauroa.server.db.command.AbstractDBCommand;
import marauroa.server.game.db.DAORegister;
public class ReadAchievementsForPlayerCommand extends AbstractDBCommand {
private Set<String> identifiers = new HashSet<String>();
private final Player player;
/**
* @param player the player whose achievements should be read
*/
public ReadAchievementsForPlayerCommand(Player player) {
this.player = player;
}
@Override
public void execute(DBTransaction transaction) throws SQLException,
IOException {
identifiers = DAORegister.get().get(AchievementDAO.class).loadAllReachedAchievementsOfPlayer(getPlayer().getName(), transaction);
}
public Set<String> getIdentifiers() {
return identifiers;
}
public Player getPlayer() {
return player;
}
}

View file

@ -1,43 +0,0 @@
package games.stendhal.server.core.engine.dbcommand;
import games.stendhal.server.core.engine.db.AchievementDAO;
import games.stendhal.server.core.events.achievements.Achievement;
import java.io.IOException;
import java.sql.SQLException;
import marauroa.server.db.DBTransaction;
import marauroa.server.db.command.AbstractDBCommand;
import marauroa.server.game.db.DAORegister;
public class WriteAchievementCommand extends AbstractDBCommand {
private final Achievement achievement;
private Integer savedId;
/**
* @param achievement
*/
/**
* @param achievement
*/
public WriteAchievementCommand(Achievement achievement) {
super();
this.achievement = achievement;
}
@Override
public void execute(DBTransaction transaction) throws SQLException,
IOException {
savedId = DAORegister.get().get(AchievementDAO.class).saveAchievement(achievement.getIdentifier(), achievement.getTitle(), achievement.getCategory(), transaction);
}
/**
* @return the savedId
*/
public Integer getSavedId() {
return savedId;
}
}

View file

@ -1,39 +0,0 @@
package games.stendhal.server.core.engine.dbcommand;
import games.stendhal.server.core.engine.db.AchievementDAO;
import games.stendhal.server.core.events.achievements.Category;
import java.io.IOException;
import java.sql.SQLException;
import marauroa.server.db.DBTransaction;
import marauroa.server.db.command.AbstractDBCommand;
import marauroa.server.game.db.DAORegister;
/**
* command to log a reached achievement to the database
*
* @author madmetzger
*/
public class WriteReachedAchievementCommand extends AbstractDBCommand {
private final Integer id;
private final String playerName;
/**
* create a new command
* @param id database id of the achievement
* @param playerName name of player who has reached it
*/
public WriteReachedAchievementCommand(Integer id, String title, Category category, String playerName) {
this.id = id;
this.playerName = playerName;
}
@Override
public void execute(DBTransaction transaction) throws SQLException,
IOException {
AchievementDAO dao = DAORegister.get().get(AchievementDAO.class);
dao.saveReachedAchievement(id, playerName, transaction);
}
}

View file

@ -1,83 +0,0 @@
package games.stendhal.server.core.events.achievements;
import games.stendhal.server.entity.npc.ChatCondition;
import games.stendhal.server.entity.player.Player;
/**
* An Achievement a player can reach while playing the game.
* Achievements are given for example for doing a certain number of quests or killing a number of special creatures
*
* @author madmetzger
*/
public class Achievement {
private final String identifier;
private final String title;
private final Category category;
private final String description;
private final ChatCondition condition;
/**
* create a new achievement
*
* @param identifier
* @param title
* @param category
* @param condition
*/
public Achievement(String identifier, String title, Category category, String description, ChatCondition condition) {
this.identifier = identifier;
this.title = title;
this.category = category;
this.condition = condition;
this.description = description;
}
/**
* @return the category of this achievement
*/
public Category getCategory() {
return category;
}
/**
* @return the identifying string
*/
public String getIdentifier() {
return identifier;
}
/**
* @return the title a player gets awarded for this achievement
*/
public String getTitle() {
return title;
}
/**
* @return the description of what to do to get this achievement
*/
public String getDescription() {
return description;
}
/**
* Check if a player has fullfilled this achievement
* @param p the player to check
* @return true iff this achievement's condtion evalutates to true
*/
public boolean isFulfilled(Player p) {
boolean fullfilled = condition.fire(p, null, null);
return fullfilled;
}
@Override
public String toString() {
return "Achievement<id: "+identifier+", title: "+title+">";
}
}

View file

@ -1,260 +0,0 @@
package games.stendhal.server.core.events.achievements;
import games.stendhal.server.core.engine.GameEvent;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.dbcommand.ReadAchievementIdentifierToIdMap;
import games.stendhal.server.core.engine.dbcommand.WriteAchievementCommand;
import games.stendhal.server.core.engine.dbcommand.WriteReachedAchievementCommand;
import games.stendhal.server.entity.npc.condition.LevelGreaterThanCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasKilledNumberOfCreaturesCondition;
import games.stendhal.server.entity.player.Player;
import games.stendhal.server.entity.player.ReadAchievementsOnLogin;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import marauroa.server.db.command.DBCommandQueue;
import marauroa.server.db.command.ResultHandle;
/**
* Checks for reached achievements and marks them as reached for a player if he has fullfilled them
*
* @author madmetzger
*/
public class AchievementNotifier {
private static AchievementNotifier instance;
private Map<Category, List<Achievement>> achievements;
private Map<String, Integer> identifiersToIds;
private ResultHandle handle = new ResultHandle();
private AchievementNotifier() {
achievements = new HashMap<Category, List<Achievement>>();
identifiersToIds = new HashMap<String, Integer>();
}
/**
* singleton accessor method
*
* @return the AchievementNotifier
*/
public static AchievementNotifier get() {
if(instance == null) {
instance = new AchievementNotifier();
}
return instance;
}
/**
* initializes the achievements that are available and registers the login listener
* new added achievements are added to the achievements table
*/
public void initialize() {
Map<String, Achievement> allAchievements = createAchievements();
for(Achievement a : allAchievements.values()) {
if(!achievements.containsKey(a.getCategory())) {
achievements.put(a.getCategory(), new LinkedList<Achievement>());
}
achievements.get(a.getCategory()).add(a);
}
Set<String> allIdentifiersInDatabase = collectAllIdentifiersFromDatabase();
for(String identifier : allIdentifiersInDatabase) {
allAchievements.remove(identifier);
}
for (Achievement a : allAchievements.values()) {
WriteAchievementCommand command = new WriteAchievementCommand(a);
DBCommandQueue.get().enqueueAndAwaitResult(command, handle);
Integer id = command.getSavedId();
identifiersToIds.put(a.getIdentifier(), id);
}
SingletonRepository.getLoginNotifier().addListener(new ReadAchievementsOnLogin());
}
/**
* collects all identifiers from the database
*
* @return a set of all identifier strings
*/
private Set<String> collectAllIdentifiersFromDatabase() {
DBCommandQueue.get().enqueueAndAwaitResult(new ReadAchievementIdentifierToIdMap(), handle);
ReadAchievementIdentifierToIdMap command = waitForResult();
Map<String, Integer> mapFromDB = command.getIdentifierToIdMap();
identifiersToIds.putAll(mapFromDB);
return mapFromDB.keySet();
}
/**
* waits for the result of an issued ReadAchievementIdentifierToIdMap command
*
* @return the completed command
*/
private ReadAchievementIdentifierToIdMap waitForResult() {
ReadAchievementIdentifierToIdMap command = DBCommandQueue.get().getOneResult(ReadAchievementIdentifierToIdMap.class, handle);
while(command == null) {
command = DBCommandQueue.get().getOneResult(ReadAchievementIdentifierToIdMap.class, handle);
}
return command;
}
/**
* checks all for level change relevant achievements for a player
*
* @param player
*/
public void onLevelChange(Player player) {
getAndCheckAchievementsInCategory(player, Category.EXPERIENCE);
}
/**
* checks all achievements for a player that should be checked when a player kills sth
*
* @param player
*/
public void onKill(Player player) {
getAndCheckAchievementsInCategory(player, Category.FIGHTING);
}
/**
* check all achievements for a player that are relevant on finishing a quest
*
* @param player
*/
public void onFinishQuest(Player player) {
getAndCheckAchievementsInCategory(player, Category.QUEST);
}
/**
* retrieve all achievements for a category and check if player has reached each of the found achievements
*
* @param player
* @param category
*/
private void getAndCheckAchievementsInCategory(Player player, Category category) {
if(achievements.containsKey(category)) {
List<Achievement> toCheck = achievements.get(category);
checkAchievements(player, toCheck);
}
}
/**
* checks for each achievement if the player has reached it. in case of reaching
* an achievement it starts logging and notifying about reaching
*
* @param player
* @param toCheck
*/
private void checkAchievements(Player player,
List<Achievement> toCheck) {
for (Achievement achievement : toCheck) {
if(achievement.isFulfilled(player) && !player.hasReachedAchievement(achievement.getIdentifier())) {
notifyPlayerAboutReachedAchievement(player, achievement);
logReachingOfAnAchievement(player, achievement);
}
}
}
/**
* logs reached achievement to gameEvents table and reached_achievment table
*
* @param player
* @param achievement
*/
private void logReachingOfAnAchievement(Player player, Achievement achievement) {
String identifier = achievement.getIdentifier();
String title = achievement.getTitle();
Category category = achievement.getCategory();
String playerName = player.getName();
DBCommandQueue.get().enqueue(new WriteReachedAchievementCommand(identifiersToIds.get(identifier), title, category, playerName));
player.addReachedAchievement(achievement.getIdentifier());
new GameEvent(playerName, "reach-achievement", category.toString(), title, identifier).raise();
}
/**
* notifies the player about reaching an achievement
*
* @param player
* @param achievement
*/
private void notifyPlayerAboutReachedAchievement(Player player,
Achievement achievement) {
//TODO: use postman here?
//player.sendPrivateText("Congratulations! You have reached the "+achievement.getTitle()+" achievement!");
}
/**
* creates all available achievements
*
* @return map with key identifier and value the identified achievement
*/
private Map<String, Achievement> createAchievements() {
Map<String, Achievement> achievementMap = new HashMap<String, Achievement>();
for(Achievement a : createExperienceAchievements()) {
achievementMap.put(a.getIdentifier(), a);
}
for(Achievement a : createFightingAchievements()) {
achievementMap.put(a.getIdentifier(), a);
}
for(Achievement a : createQuestAchievements()) {
achievementMap.put(a.getIdentifier(), a);
}
return achievementMap;
}
/**
* creates a collection of all available fighting achievements
*
* @return
*/
private Collection<Achievement> createFightingAchievements() {
List<Achievement> fightingAchievements = new LinkedList<Achievement>();
Achievement killRats = new Achievement("fight.general.rats", "Rat hunter",
Category.FIGHTING, "Kill 15 rats",
new PlayerHasKilledNumberOfCreaturesCondition("rat", 15));
Achievement exterminator = new Achievement("fight.general.exterminator", "Exterminator",
Category.FIGHTING, "Kill 10 rats of each kind",
new PlayerHasKilledNumberOfCreaturesCondition(10, "rat", "caverat", "venomrat", "zombie rat", "venom rat", "giantrat", "ratman", "ratwoman", "archrat"));
fightingAchievements.add(killRats);
fightingAchievements.add(exterminator);
return fightingAchievements;
}
/**
* creates a collection of all experience related achievements
*
* @return
*/
private Collection<Achievement> createExperienceAchievements() {
List<Achievement> xpAchievements = new LinkedList<Achievement>();
Achievement newbie = new Achievement("xp.lvl.10", "Greenhorn",
Category.EXPERIENCE, "Reach level 10",
new LevelGreaterThanCondition(9));
Achievement newbie50 = new Achievement("xp.lvl.50", "Apprentice",
Category.EXPERIENCE, "Reach level 50",
new LevelGreaterThanCondition(49));
Achievement newbie100 = new Achievement("xp.lvl.100", "Apprentice",
Category.EXPERIENCE, "Reach level 100",
new LevelGreaterThanCondition(99));
xpAchievements.add(newbie);
xpAchievements.add(newbie50);
xpAchievements.add(newbie100);
return xpAchievements;
}
/**
* creates a collection of all available quest achievements
*
* @return
*/
private Collection<Achievement> createQuestAchievements() {
List<Achievement> questAchievements = new LinkedList<Achievement>();
return questAchievements;
}
}

View file

@ -1,12 +0,0 @@
/**
*
*/
package games.stendhal.server.core.events.achievements;
/**
* categories of achievements
*
* @author madmetzger
*/
public enum Category {
EXPERIENCE, FIGHTING, QUEST
}

View file

@ -1134,7 +1134,6 @@ public abstract class RPEntity extends GuidedEntity {
}
killer.addXP(reward);
SingletonRepository.getAchievementNotifier().onKill(killer);
// For some quests etc., it is required that the player kills a
// certain creature without the help of others.
// Find out if the player killed this RPEntity on his own, but

View file

@ -39,7 +39,9 @@ public class MessagingArea extends AreaEntity implements MovementListener {
public void onEntered(final ActiveEntity entity, final StendhalRPZone zone, final int newX, final int newY) {
if ((enterMessage != null) && (entity instanceof Player)) {
((Player) entity).sendPrivateText(NotificationType.SCENE_SETTING, enterMessage);
// needs to be delayed to avoid the message appearing before server
// welcome on login
new DelayedPlayerTextSender((Player) entity, enterMessage, NotificationType.SCENE_SETTING, 1);
}
}

View file

@ -1,15 +0,0 @@
package games.stendhal.server.entity.npc.action;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.parser.Sentence;
import games.stendhal.server.entity.player.Player;
public class CheckForReachedQuestAchievements implements ChatAction {
public void fire(Player player, Sentence sentence, EventRaiser npc) {
SingletonRepository.getAchievementNotifier().onFinishQuest(player);
}
}

View file

@ -0,0 +1,64 @@
package games.stendhal.server.entity.npc.action;
import games.stendhal.common.NotificationType;
import games.stendhal.server.entity.npc.ChatAction;
import games.stendhal.server.entity.npc.EventRaiser;
import games.stendhal.server.entity.npc.parser.Sentence;
import games.stendhal.server.entity.player.Player;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
/**
* Sends the message as a private text
* Optional notification type when used with NPCs
*/
public class SendPrivateMessageAction implements ChatAction {
private final String text;
private final NotificationType type;
/**
* Creates a new SendPrivateMessageAction.
*
* @param text text to send
*/
public SendPrivateMessageAction(String text) {
this.text = text;
this.type = NotificationType.PRIVMSG;
}
/**
* Creates a new SendPrivateMessageAction - does NOT work with portals
*
* @param text text to send
*
* @param type type of message
*/
public SendPrivateMessageAction(final NotificationType type, final String text) {
this.text = text;
this.type = type;
}
public void fire(final Player player, final Sentence sentence, final EventRaiser raiser) {
player.sendPrivateText(type, text);
}
@Override
public String toString() {
// would need to send the type toString also to include the type here
return "Send Private Message: " + text;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(final Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false,
SendPrivateMessageAction.class);
}
}

View file

@ -68,7 +68,7 @@ public class StartRecordingRandomItemCollectionAction implements ChatAction {
final int quantity = items.get(itemname);
Map<String, String> substitutes = new HashMap<String, String>();
substitutes.put("item", Grammar.quantityplnoun(quantity, itemname));
substitutes.put("item", Grammar.quantityplnoun(quantity, itemname, "a"));
substitutes.put("#item", Grammar.quantityplnounWithHash(quantity, itemname));
substitutes.put("the item", "the " + Grammar.plnoun(quantity, itemname));

View file

@ -12,6 +12,12 @@
***************************************************************************/
package games.stendhal.server.entity.player;
import static games.stendhal.common.constants.Actions.ADMINLEVEL;
import static games.stendhal.common.constants.Actions.AWAY;
import static games.stendhal.common.constants.Actions.GHOSTMODE;
import static games.stendhal.common.constants.Actions.GRUMPY;
import static games.stendhal.common.constants.Actions.INVISIBLE;
import static games.stendhal.common.constants.Actions.TELECLICKMODE;
import games.stendhal.common.Constants;
import games.stendhal.common.Direction;
import games.stendhal.common.FeatureList;
@ -23,7 +29,6 @@ import games.stendhal.common.constants.Nature;
import games.stendhal.server.core.engine.SingletonRepository;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.events.TutorialNotifier;
import games.stendhal.server.core.events.achievements.AchievementNotifier;
import games.stendhal.server.core.rp.StendhalRPAction;
import games.stendhal.server.entity.Entity;
import games.stendhal.server.entity.Outfit;
@ -42,7 +47,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
@ -54,13 +58,6 @@ import marauroa.common.game.SyntaxException;
import org.apache.log4j.Logger;
import static games.stendhal.common.constants.Actions.ADMINLEVEL;
import static games.stendhal.common.constants.Actions.AWAY;
import static games.stendhal.common.constants.Actions.GHOSTMODE;
import static games.stendhal.common.constants.Actions.GRUMPY;
import static games.stendhal.common.constants.Actions.INVISIBLE;
import static games.stendhal.common.constants.Actions.TELECLICKMODE;
public class Player extends RPEntity {
private static final String LAST_PLAYER_KILL_TIME = "last_player_kill_time";
@ -135,11 +132,6 @@ public class Player extends RPEntity {
private String lastPrivateChatterName;
private final PlayerChatBucket chatBucket;
/**
* all identifiers of reached achievements, filled on login of player
*/
private Set<String> reachedAchievements = new HashSet<String>();
public static void generateRPClass() {
try {
@ -2060,22 +2052,4 @@ public class Player extends RPEntity {
remove("buddies", name);
}
@Override
public void setLevel(int level) {
super.setLevel(level);
AchievementNotifier.get().onLevelChange(this);
}
public void addReachedAchievement(String identifier) {
getAchievements().add(identifier);
}
private Set<String> getAchievements() {
return reachedAchievements;
}
public boolean hasReachedAchievement(String identifier) {
return getAchievements().contains(identifier);
}
}

View file

@ -1,37 +0,0 @@
package games.stendhal.server.entity.player;
import games.stendhal.server.core.engine.dbcommand.ReadAchievementsForPlayerCommand;
import games.stendhal.server.core.events.LoginListener;
import games.stendhal.server.core.events.TurnListener;
import games.stendhal.server.core.events.TurnNotifier;
import java.util.Set;
import marauroa.server.db.command.DBCommand;
import marauroa.server.db.command.DBCommandQueue;
import marauroa.server.db.command.ResultHandle;
public class ReadAchievementsOnLogin implements LoginListener, TurnListener {
private ResultHandle handle = new ResultHandle();
public void onLoggedIn(Player player) {
DBCommand command = new ReadAchievementsForPlayerCommand(player);
DBCommandQueue.get().enqueueAndAwaitResult(command, handle);
TurnNotifier.get().notifyInTurns(1, this);
}
public void onTurnReached(int currentTurn) {
ReadAchievementsForPlayerCommand command = DBCommandQueue.get().getOneResult(ReadAchievementsForPlayerCommand.class, handle);
if (command == null) {
TurnNotifier.get().notifyInTurns(0, this);
return;
}
Player p = command.getPlayer();
Set<String> identifiers = command.getIdentifiers();
for (String identifier : identifiers) {
p.addReachedAchievement(identifier);
}
}
}

View file

@ -279,8 +279,10 @@ public abstract class UpdateConverter {
}
//port to 0.86: port keymap to feature map, karama_indicator as feature
if (KeyedSlotUtil.getKeyedSlot(object, "!features", "keyring") != null) {
object.put("features", "keyring", "");
if (object.hasSlot("!features")) {
if (KeyedSlotUtil.getKeyedSlot(object, "!features", "keyring") != null) {
object.put("features", "keyring", "");
}
}
if (KeyedSlotUtil.getKeyedSlot(object, "!quests", "learn_karma") != null) {
object.put("features", "karma_indicator", "");

View file

@ -37,7 +37,7 @@ public class DwarfBuyerGuyNPC extends SpeakerNPCFactory {
offerings.put("magical needle", 1000);
offerings.put("snowglobe", 150);
offerings.put("silk gland", 500);
new BuyerAdder().add(dwarfguy, new BuyerBehaviour(offerings), true);
new BuyerAdder().add(dwarfguy, new BuyerBehaviour(offerings), false);
}
}

View file

@ -54,7 +54,7 @@ public class KirdnehFishyMarketNPC implements ZoneConfigurator {
addReply("aye", "Well, shiver me timbers! Check out that blackboard o'er thar fer me prices an' what i be buyin");
addReply("no", "You lily-livered scallywag! Why ye be wastin me time?");
addHelp("An' just what do ya think a buccanneer such as meself could possibly help ye with?");
new BuyerAdder().add(this, new BuyerBehaviour(shops.get("buyfishes")), true);
new BuyerAdder().add(this, new BuyerBehaviour(shops.get("buyfishes")), false);
addOffer("Check out that thar blackboard fer how many dubloons I be givin.");
addQuest("Ye don't ha'e the guts ta do whut I need done.");
addGoodbye("Arrgh, avast an' be gone with ye!");

View file

@ -22,7 +22,7 @@ public class ChiefFalatheenDishwasherNPC extends SpeakerNPCFactory {
dishwasher.addQuest("You could try to help me #escape from these hoodlums. Well... maybe not.");
dishwasher.addGoodbye("Don't forget where I am now. Come back and see me some time. I do get lonely.");
dishwasher.addReply("escape", "Yes! I want to pursue my dream. Mother Helena offered me a most wonderful job. She needs a dishwasher. Lots of complaining customers!!!");
new BuyerAdder().add(dishwasher, new BuyerBehaviour(shops.get("buyveggiesandherbs")), true);
new BuyerAdder().add(dishwasher, new BuyerBehaviour(shops.get("buyveggiesandherbs")), false);
}
}

View file

@ -33,7 +33,7 @@ public class ArcheryDealerNPC extends SpeakerNPCFactory {
offerings.put("composite bow", 350);
offerings.put("hunter crossbow", 800);
offerings.put("mithril bow", 2000);
new BuyerAdder().add(magearcher, new BuyerBehaviour(offerings), true);
new BuyerAdder().add(magearcher, new BuyerBehaviour(offerings), false);
}
}

View file

@ -4,16 +4,8 @@ import games.stendhal.server.core.config.ZoneConfigurator;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.core.pathfinder.FixedPath;
import games.stendhal.server.core.pathfinder.Node;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -64,31 +56,40 @@ public class BlueIceSorceressNPC implements ZoneConfigurator {
@Override
protected void createDialog() {
addGreeting("Hello dear!");
addHelp("I can conjure an #ice #scroll for you. It is able to protect you from dangerous heat, depends on how you use it.");
//addHelp("I can conjure an #ice #scroll for you. It can't help you in the battle. But it can protect you from natural heat on certain dangerous terrains. You will know when you need it.");
addHelp("Excuse me, I am very busy establishing the sorceresses part at the wizards circle.");
addJob("I am Cassandra, the sorceress of water and ice. I represent #Frostshade at the wizards circle.");
addOffer("I can conjure an #ice #scroll for you. It is able to protect you from dangerous heat, depends on how you use it.");
//addOffer("I can conjure an #ice #scroll for you. It can't help you in the battle. But it can protect you from natural heat on certain dangerous terrains. You will know when you need it.");
addOffer("Excuse me, I am very busy establishing the sorceresses part at the wizards circle.");
addReply("Frostshade", "Frostshade is the school of the magic of water and ice. It lies deep in the northern glaciers.");
addReply("scroll", "Zekiel is the storekeeper of the tower, I am sure he can help you.");
addReply("blank scroll", "Zekiel is the storekeeper of the tower, I am sure he can help you.");
addQuest("The magic in this world has just begun and I am very busy to establish the sorceresses of #Frostshade at the wizards circle. I will tell you in time, when I have a quest for you.");
addGoodbye("Bye!");
addReply(Arrays.asList("ice scroll", "ice scrolls"),
"I need a #scroll for that. If you bring me one, I will #enchant it for you.");
add(
ConversationStates.ATTENDING,
Arrays.asList("enchant"),
new PlayerHasItemWithHimCondition("scroll"),
ConversationStates.ATTENDING,
"I enchanted your scroll to an ice scroll. May it cool off your feets on your travels.",
new MultipleActions(
new DropItemAction("scroll", 1),
new EquipItemAction("ice scroll", 1, true),
new IncreaseXPAction(250)));
add(
ConversationStates.ATTENDING,
Arrays.asList("enchant"),
new NotCondition(new PlayerHasItemWithHimCondition("scroll")),
ConversationStates.ATTENDING,
"You don't have a #scroll that I could enchant.", null);
/** addReply(Arrays.asList("ice scroll", "ice scrolls"),
* "I need a #blank #scroll for that. If you bring me one, I will #enchant it for you.");
* add(
* ConversationStates.ATTENDING,
* Arrays.asList("enchant"),
* new PlayerHasItemWithHimCondition("blank scroll"),
* ConversationStates.ATTENDING,
* "I enchanted your blank scroll to an ice scroll. May it cool off your feets on your travels.",
* new MultipleActions(
* new DropItemAction("blank scroll", 1),
* new EquipItemAction("ice scroll", 1, true),
* new IncreaseXPAction(250)));
* add(
* ConversationStates.ATTENDING,
* Arrays.asList("enchant"),
* new NotCondition(new PlayerHasItemWithHimCondition("blank scroll")),
* ConversationStates.ATTENDING,
* "You don't have a #blank #scroll that I could enchant.", null);
*/
} //remaining behaviour defined in maps.quests.SorceressCassandraPlainQuest
};

View file

@ -2,16 +2,7 @@ package games.stendhal.server.maps.semos.wizardstower;
import games.stendhal.server.core.config.ZoneConfigurator;
import games.stendhal.server.core.engine.StendhalRPZone;
import games.stendhal.server.entity.npc.ConversationPhrases;
import games.stendhal.server.entity.npc.ConversationStates;
import games.stendhal.server.entity.npc.SpeakerNPC;
import games.stendhal.server.entity.npc.action.DropItemAction;
import games.stendhal.server.entity.npc.action.EquipItemAction;
import games.stendhal.server.entity.npc.action.IncreaseXPAction;
import games.stendhal.server.entity.npc.action.MultipleActions;
import games.stendhal.server.entity.npc.condition.AndCondition;
import games.stendhal.server.entity.npc.condition.NotCondition;
import games.stendhal.server.entity.npc.condition.PlayerHasItemWithHimCondition;
import java.util.Arrays;
import java.util.Map;
@ -42,10 +33,15 @@ public class WizardsGuardStatueSpireNPC implements ZoneConfigurator {
addHelp("You are stood in the #store. You can enter the spire by the teleporter in front of me. The one behind me teleports you back to the tower entrance.");
addJob("I am the guardian and #storekeeper of the #wizards tower.");
addGoodbye("So long!");
addOffer("I can create #special items with the materials from the store. Just tell me what you want, but for most items I will need extra ingredients.");
addReply(Arrays.asList("store", "storekeeper"),
"I can create #special items with the materials from the store. Just tell me what you want, but for the most items I will need extra ingredients.");
"I can create #special items with the materials from the store. Just tell me what you want, but for most items I will need extra ingredients.");
// addReply("special",
// "For example I can create a #rift #cloak. I could read in your mind, adventurer. But it is not allowed to me here. So you have to tell me which special item you want and I will tell you, if I can help you.");
addReply("special",
"For example I can create a #rift #cloak. I could read in your mind, adventurer. But it is not allowed to me here. So you have to tell me which special item you want and I will tell you, if I can help you.");
"I am sorry, now is not the time. Try again in some weeks, and I may be ready to help you.");
addReply(Arrays.asList("wizard", "wizards"),
"Seven wizards form the wizards circle. These are #Erastus, #Elana, #Ravashack, #Jaer, #Cassandra, #Silvanus and #Malleus");
addReply("erastus", "Erastus is the archmage of the wizards circle. He is the grandmaster of all magics and the wisest person that is known. He is the only one without a part in the practical test.");
@ -56,11 +52,11 @@ public class WizardsGuardStatueSpireNPC implements ZoneConfigurator {
addReply("silvanus", "Silvanus is a sage druid and perhaps the eldest of all elves. He is a friend of all animals, trees, fairy creatures and ents. His domain is Earth and Nature.");
addReply("malleus", "Malleus is the powerful archetype of a magician and the master of destructive magics. His domain is Fire and he rambled the plains of demons for ages, to understand their ambitions.");
// behavior on special item SCROLL
/** // behavior on special item BLANK SCROLL
add(ConversationStates.ATTENDING,
Arrays.asList("scroll", "scrolls"),
Arrays.asList("blank scroll", "scrolls"),
ConversationStates.INFORMATION_1,
"I will create a magic scroll for you, but I need eight pieces of wood for that. The scroll will be empty and can be enchanted by wizards. Do you want a magic scroll?",
"I will create a blank scroll for you, but I need eight pieces of wood for that. The blank scroll can be enchanted by wizards. Do you want a blank scroll?",
null);
add(ConversationStates.INFORMATION_1,
ConversationPhrases.YES_MESSAGES,
@ -72,16 +68,16 @@ public class WizardsGuardStatueSpireNPC implements ZoneConfigurator {
ConversationPhrases.YES_MESSAGES,
new PlayerHasItemWithHimCondition("wood", 8),
ConversationStates.ATTENDING,
"There is your magic scroll.",
"There is your blank scroll.",
new MultipleActions(
new DropItemAction("wood", 8),
new EquipItemAction("scroll", 1, true),
new EquipItemAction("blank scroll", 1, true),
new IncreaseXPAction(250)));
add(ConversationStates.INFORMATION_1,
ConversationPhrases.NO_MESSAGES,
null,
ConversationStates.ATTENDING,
"Well, maybe later. Just tell me when you want a magic scroll.",
"Well, maybe later. Just tell me when you want a blank scroll.",
null);
//behavior on special item RIFT CLOAK
@ -124,6 +120,7 @@ public class WizardsGuardStatueSpireNPC implements ZoneConfigurator {
ConversationStates.ATTENDING,
"Don't forget that you can't enter a magical rift without a rift cloak.",
null);
*/
//behavior on special item XARUHWAIYZ PHIAL
} //remaining behavior defined in maps.quests.ZekielsPracticalTestQuest

View file

@ -1,6 +1,10 @@
package games.stendhal.server.script;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import games.stendhal.server.core.scripting.ScriptImpl;
import games.stendhal.server.entity.player.Player;
@ -36,27 +40,34 @@ public class DumpPostmanTable extends ScriptImpl {
} catch (final Exception e) {
admin.sendPrivateText("Could not find postman file");
}
final Iterator< ? > itr = messages.keySet().iterator();
while (itr.hasNext()) {
final String key = itr.next().toString();
String target = key.substring(0,key.indexOf("!"));
String source = key.substring(key.indexOf("!") + 1);
String message = messages.getProperty(key);
// messages got grouped together, but the line breaks will confuse the csv file: replace new lines with spaces.
message = message.replace("\n", " ");
// replace any double quotes in there with two single quotes so we don't confuse mysql on import
message = message.replace("\"", "''");
// replace any escape characters
message = message.replace("\\", "\\\\");
// well, why not clean it now.
message = message.trim();
System.out.println("\"" + source + "\",\"" + target + "\",\"" + message + "\"");
itr.remove();
PrintStream out;
try {
out = new PrintStream(new FileOutputStream("postmantable.csv"));
final Iterator< ? > itr = messages.keySet().iterator();
while (itr.hasNext()) {
final String key = itr.next().toString();
String target = key.substring(0,key.indexOf("!"));
String source = key.substring(key.indexOf("!") + 1);
String message = messages.getProperty(key);
// messages got grouped together, but the line breaks will confuse the csv file: replace new lines with spaces.
message = message.replace("\n", " ");
// replace any double quotes in there with two single quotes so we don't confuse mysql on import
message = message.replace("\"", "''");
// replace any escape characters
message = message.replace("\\", "\\\\");
// well, why not clean it now.
message = message.trim();
out.println("\"" + source + "\",\"" + target + "\",\"" + message + "\"");
itr.remove();
}
out.close();
} catch (FileNotFoundException e) {
admin.sendPrivateText("Could not find postmantable.csv to print to");
}
}
}

View file

@ -162,24 +162,3 @@ CREATE TABLE IF NOT EXISTS buddy (
);
/* CREATE INDEX i_buddy_charname ON buddy (charname); */
CREATE TABLE IF NOT EXISTS achievement (
id INTEGER AUTO_INCREMENT NOT NULL,
identifier VARCHAR(64),
title VARCHAR(64),
category VARCHAR(64),
description VARCHAR(64),
PRIMARY KEY(id)
);
/* CREATE UNIQUE INDEX i_achievement_identifier ON achievement(identifier);*/
CREATE TABLE IF NOT EXISTS reached_achievement (
id INTEGER AUTO_INCREMENT NOT NULL,
charname VARCHAR(32),
timedate TIMESTAMP default CURRENT_TIMESTAMP,
achievement_id INTEGER,
PRIMARY KEY(id)
);
/* CREATE INDEX i_reached_achievement_charname ON reached_achievement(charname);*/

View file

@ -22,7 +22,7 @@ Some of these people are NPC, they will give you tasks to accomplish and hints t
</security>
<resources>
<j2se href="http://java.sun.com/products/autodl/j2se" version="1.5+" /> <!-- max-heap-size="120" -->
<jar href="http://arianne.sourceforge.net/jws/stendhal-starter-0.85.5.jar" download="eager" main="true" />
<jar href="http://arianne.sourceforge.net/jws/stendhal-starter-0.86.jar" download="eager" main="true" />
</resources>
<application-desc/>
</jnlp>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

After

Width:  |  Height:  |  Size: 360 KiB

Before After
Before After