diff --git a/data/conf/zones/deniran.xml b/data/conf/zones/deniran.xml index 043d84d280c..9f2390acdf7 100644 --- a/data/conf/zones/deniran.xml +++ b/data/conf/zones/deniran.xml @@ -1429,6 +1429,7 @@ Entrance fee is 10 money + diff --git a/data/sprites/outfit/detail/016-blacksmith_hammer.xcf.bz2 b/data/sprites/outfit/detail/016-blacksmith_hammer.xcf.bz2 new file mode 100644 index 00000000000..4185a7995f3 Binary files /dev/null and b/data/sprites/outfit/detail/016-blacksmith_hammer.xcf.bz2 differ diff --git a/data/sprites/outfit/detail/016-rear.png b/data/sprites/outfit/detail/016-rear.png new file mode 100644 index 00000000000..ad4123a67d1 Binary files /dev/null and b/data/sprites/outfit/detail/016-rear.png differ diff --git a/data/sprites/outfit/detail/016.png b/data/sprites/outfit/detail/016.png new file mode 100644 index 00000000000..58a57781baa Binary files /dev/null and b/data/sprites/outfit/detail/016.png differ diff --git a/data/sprites/outfit/hair/057.png b/data/sprites/outfit/hair/057.png new file mode 100644 index 00000000000..e446dec0868 Binary files /dev/null and b/data/sprites/outfit/hair/057.png differ diff --git a/data/sprites/outfit/outfits.json b/data/sprites/outfit/outfits.json index 392dfa86dcf..9bccb61fd79 100644 --- a/data/sprites/outfit/outfits.json +++ b/data/sprites/outfit/outfits.json @@ -1,5 +1,5 @@ { "detail": { - "rear": [1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15] + "rear": [1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16] } } diff --git a/doc/CHANGES.txt b/doc/CHANGES.txt index 5f864c97dff..784b3d242c2 100644 --- a/doc/CHANGES.txt +++ b/doc/CHANGES.txt @@ -9,6 +9,8 @@ Changelog - added music to Athor Island - Mayor Chalmers won't accept experimental sandwiches for Daily Item Quest - touched up and added equipment to many entity sprites +- new player selectable hair +- new NPC Tinny *chat* - new offers with Harold are announced in chat diff --git a/doc/sources/graphics-outfit.txt b/doc/sources/graphics-outfit.txt index a4877d0a9b3..f14f33f2aed 100644 --- a/doc/sources/graphics-outfit.txt +++ b/doc/sources/graphics-outfit.txt @@ -27,19 +27,20 @@ data/sprites/outfit/body/ data/sprites/outfit/detail/ 000 (empty) -00[1-3] (balloon) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal, https://opengameart.org/node/101299 -004 (bone) Bart Kelsey; CC0; https://opengameart.org/node/3755 -005 (flag) Kimmo Rundelin (kiheru); CC BY-SA 3.0; Stendhal -006 (cane) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal -007 (umbrella) Diligent Dodo (soniccuz), Jordan Irwin (AntumDeluge); CC BY-SA 3.0; https://sourceforge.net/p/arianne/patches/687/ -008 (sword) LordNeo; CC0; https://opengameart.org/node/10878 -009 (knife) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal -010 (spear) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal -011 (bow) Michael Williams (BizmasterStudios); CC BY 3.0; https://opengameart.org/node/66349 -012 (axe) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal -013 (axe) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal -014 (kite shield) Michael Williams (BizmasterStudios); CC BY 3.0; https://opengameart.org/node/64857 -015 (shield) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +00[1-3] (balloon) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal, https://opengameart.org/node/101299 +004 (bone) Bart Kelsey; CC0; https://opengameart.org/node/3755 +005 (flag) Kimmo Rundelin (kiheru); CC BY-SA 3.0; Stendhal +006 (cane) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +007 (umbrella) Diligent Dodo (soniccuz), Jordan Irwin (AntumDeluge); CC BY-SA 3.0; https://sourceforge.net/p/arianne/patches/687/ +008 (sword) LordNeo; CC0; https://opengameart.org/node/10878 +009 (knife) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +010 (spear) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +011 (bow) Michael Williams (BizmasterStudios); CC BY 3.0; https://opengameart.org/node/66349 +012 (axe) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +013 (axe) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +014 (kite shield) Michael Williams (BizmasterStudios); CC BY 3.0; https://opengameart.org/node/64857 +015 (shield) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +016 (blacksmith hammer) Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal, https://opengameart.org/node/82370 data/sprites/outfit/dress/ @@ -241,6 +242,7 @@ data/sprites/outfit/hair/ 054 diamonddmgirl, Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal, https://opengameart.org/node/72198 055 Yamilian; CC BY-SA 3.0; https://opengameart.org/node/11445 056 Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal +057 Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal 998 Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal 999 diamonddmgirl, bleutailfly, Jordan Irwin (AntumDeluge); OGA BY 3.0; Stendhal, https://opengameart.org/node/72198 diff --git a/src/games/stendhal/common/Outfits.java b/src/games/stendhal/common/Outfits.java index 83d96d62956..02e080741eb 100644 --- a/src/games/stendhal/common/Outfits.java +++ b/src/games/stendhal/common/Outfits.java @@ -1,6 +1,6 @@ /* $Id$ */ /*************************************************************************** - * (C) Copyright 2003-2010 - Stendhal * + * (C) Copyright 2003-2024 - Stendhal * *************************************************************************** *************************************************************************** * * @@ -34,7 +34,7 @@ public class Outfits { public static final int CLOTHES_OUTFITS = 65; /** number of player selectable hair styles */ - public static final int HAIR_OUTFITS = 57; + public static final int HAIR_OUTFITS = 58; /** number of player selectable body shapes */ public static final int BODY_OUTFITS = 3; diff --git a/src/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPC.java b/src/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPC.java new file mode 100644 index 00000000000..9f18250dc63 --- /dev/null +++ b/src/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPC.java @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright © 2024 - Faiumoni e. V. * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.server.maps.deniran.cityinterior.tannery; + +import java.awt.Color; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import games.stendhal.common.constants.SkinColor; +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.CollisionAction; +import games.stendhal.server.entity.npc.ChatCondition; +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.condition.NotCondition; +import games.stendhal.server.entity.npc.condition.QuestRegisteredCondition; + + +public class LeatherCrafterNPC implements ZoneConfigurator { + + @Override + public void configureZone(StendhalRPZone zone, Map attributes) { + zone.add(buildNPC()); + } + + private SpeakerNPC buildNPC() { + final SpeakerNPC npc = new SpeakerNPC("Tinny"); + npc.setDescription("You see Tinny, the leather crafter."); + + buildOutfit(npc); + buildPath(npc); + buildDialogue(npc); + + return npc; + } + + private void buildOutfit(final SpeakerNPC npc) { + npc.setOutfit("body=0,head=0,eyes=3,hair=57,dress=968,mask=5,detail=16"); + npc.setOutfitColor("body", SkinColor.LIGHT); + npc.setOutfitColor("eyes", Color.BLUE); + } + + private void buildPath(final SpeakerNPC npc) { + final List nodes = new LinkedList<>(); + nodes.add(new Node(30, 4)); + nodes.add(new Node(20, 4)); + nodes.add(new Node(20, 13)); + nodes.add(new Node(30, 13)); + npc.setPath(new FixedPath(nodes, true)); + npc.setPosition(30, 4); + npc.setCollisionAction(CollisionAction.STOP); + } + + private void buildDialogue(final SpeakerNPC npc) { + npc.addGreeting("Hello, how can I help you?"); + npc.addGoodbye("Goodbye."); + npc.addJob("I am a leather crafter. I recently completed my apprenticeship under Skinner and" + + " will one day take over responsibility of the tannery."); + + final String questSlot = "items_for_tinny"; + final ChatCondition questNotRegistered = new NotCondition(new QuestRegisteredCondition(questSlot)); + + npc.add( + ConversationStates.ATTENDING, + ConversationPhrases.HELP_MESSAGES, + questNotRegistered, + ConversationStates.ATTENDING, + "If you are interested in a pouch to carry your money in, speak to Skinner.", + null); + + npc.add( + ConversationStates.ATTENDING, + ConversationPhrases.QUEST_MESSAGES, + questNotRegistered, + ConversationStates.ATTENDING, + "There is nothing I need help with at this time.", + null); + } +} diff --git a/src/games/stendhal/server/maps/quests/ItemsForTinny.java b/src/games/stendhal/server/maps/quests/ItemsForTinny.java new file mode 100644 index 00000000000..9203e1e7e54 --- /dev/null +++ b/src/games/stendhal/server/maps/quests/ItemsForTinny.java @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright © 2024 - Faiumoni e. V. * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.server.maps.quests; + +import games.stendhal.server.entity.npc.quest.BringItemQuestBuilder; +import games.stendhal.server.entity.npc.quest.QuestManuscript; +import games.stendhal.server.maps.Region; + + +public class ItemsForTinny implements QuestManuscript { + + @Override + public BringItemQuestBuilder story() { + final BringItemQuestBuilder quest = new BringItemQuestBuilder(); + + quest.info() + .name("Items for Tinny") + .internalName("items_for_tinny") + .description("Tinny the leather crafter needs to restock his shelves.") + .region(Region.DENIRAN_CITY) + .questGiverNpc("Tinny"); + + quest.history(); + + quest.offer() + .respondToRequest("Well, as a matter of fact I do have a task for you. I am in need of some" + + " supplies. Would you be interested in helping me?") + .respondToReject("Ah well, maybe I can find another brave soul to help me.") + .respondToAccept("Good! There is a few things that I need to restock my shelves. I would" + + " reward you nicely, I do love working with leather."); + + quest.task(); + + quest.complete(); + + return quest; + } +} diff --git a/src/js/stendhal/data/OutfitStore.ts b/src/js/stendhal/data/OutfitStore.ts index 10fbe6abbf6..2ddbc69c055 100644 --- a/src/js/stendhal/data/OutfitStore.ts +++ b/src/js/stendhal/data/OutfitStore.ts @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright © 2003-2023 - Arianne * + * Copyright © 2003-2024 - Arianne * *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -21,7 +21,7 @@ export class OutfitStore { // player pickable layers private count: {[key: string]: number} = { "hat": 19, - "hair": 57, + "hair": 58, "mask": 9, "eyes": 28, "mouth": 5, diff --git a/tests/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPCTest.java b/tests/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPCTest.java new file mode 100644 index 00000000000..0dc8d3d3dfa --- /dev/null +++ b/tests/games/stendhal/server/maps/deniran/cityinterior/tannery/LeatherCrafterNPCTest.java @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright © 2024 - Faiumoni e. V. * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.server.maps.deniran.cityinterior.tannery; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; +import static utilities.SpeakerNPCTestHelper.getReply; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import games.stendhal.server.core.engine.SingletonRepository; +import games.stendhal.server.entity.npc.SpeakerNPC; +import games.stendhal.server.entity.npc.fsm.Engine; +import games.stendhal.server.entity.player.Player; +import utilities.PlayerTestHelper; +import utilities.QuestHelper; +import utilities.ZonePlayerAndNPCTestImpl; + + +public class LeatherCrafterNPCTest extends ZonePlayerAndNPCTestImpl { + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + QuestHelper.setUpBeforeClass(); + setupZone("testzone"); + } + + @Override + @Before + public void setUp() throws Exception { + setZoneForPlayer("testzone"); + setNpcNames("Tinny"); + addZoneConfigurator(new LeatherCrafterNPC(), "testzone"); + + super.setUp(); + } + + @Test + public void testDialogue() { + final Player player = PlayerTestHelper.createPlayer("player"); + final SpeakerNPC npc = SingletonRepository.getNPCList().get("Tinny"); + + assertThat(player, notNullValue()); + assertThat(npc, notNullValue()); + + final Engine en = npc.getEngine(); + en.step(player, "hi"); + assertThat(getReply(npc), is("Hello, how can I help you?")); + en.step(player, "job"); + assertThat(getReply(npc), is("I am a leather crafter. I recently completed my apprenticeship" + + " under Skinner and will one day take over responsibility of the tannery.")); + en.step(player, "help"); + assertThat(getReply(npc), is("If you are interested in a pouch to carry your money in, speak to" + + " Skinner.")); + en.step(player, "task"); + assertThat(getReply(npc), is("There is nothing I need help with at this time.")); + en.step(player, "bye"); + assertThat(getReply(npc), is("Goodbye.")); + } +} diff --git a/tests/games/stendhal/server/maps/quests/ItemsForTinnyTest.java b/tests/games/stendhal/server/maps/quests/ItemsForTinnyTest.java new file mode 100644 index 00000000000..501f627b765 --- /dev/null +++ b/tests/games/stendhal/server/maps/quests/ItemsForTinnyTest.java @@ -0,0 +1,18 @@ +/*************************************************************************** + * Copyright © 2024 - Faiumoni e. V. * + *************************************************************************** + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +package games.stendhal.server.maps.quests; + +import utilities.QuestHelper; + + +public class ItemsForTinnyTest extends QuestHelper { +}