HowToAddMapsServerStendhal: Difference between revisions
imported>Chad3f |
imported>Hendrik Brummermann |
||
| (238 intermediate revisions by 7 users not shown) | |||
| Line 1: | Line 1: | ||
{{Navigation for Stendhal Top|Extending}} |
|||
{{Navigation for Stendhal Extenders}} |
|||
Of course you have already read: |
Of course you have already read: |
||
* [[HowToUseTiledToCreateStendhalMaps]] |
* [[HowToUseTiledToCreateStendhalMaps]] |
||
* [[HowToUseTiledToCreateStendhalMaps2]] |
* [[HowToUseTiledToCreateStendhalMaps2]] |
||
Ok, and I assume that you can write or at least read |
Ok, and I assume that you can write or at least read xml. |
||
= Modify map TMX file= |
|||
The maps files are just XML files with special tags, open your maps and make sure that you set x,y position of your map on the world. |
|||
Semos village is right now (500000,500000) so use something near yours to set correctly the map position. |
|||
Now you need to create the stend map files. There are two options: |
|||
* Generate it using tiled ''( Save as xstend )'' |
|||
* Run at stendhal folder: ''ant convertmaps'' |
|||
The later is prefered as it will also update world.tmx graphics. |
|||
= Modify world.tmx= |
= Modify world.tmx= |
||
Now make sure if your map is new that world.tmx shows it by adding a new tileset with your map image. |
Now make sure if your map is new that world.tmx shows it by adding a new tileset with your map image. |
||
This step is just for your mental wellness. Stendhal |
This step is just for your mental wellness. Stendhal doesn't use world.tmx. |
||
= Create a map file= |
= Create a map file= |
||
If you need to do custom zone configuration that is not possible via the "zones.xml" file (such as adding NPC's), for each zone, create one or more new Java source file(s) at '''src/games/stendhal/server/maps/<area>/<location>/<level>_<entity>.java'''. The directory path after '''maps/''' would be the same as your '''.tmx''' file uses. Ideally this would be one file per independant entity created (so they can be enabled/diabled separately). |
|||
If you are adding a zone for a new major area, create the file '''data/conf/zones/<area>.xml''' with the following: |
|||
Open the file and make sure that it looks like this: |
|||
<pre> |
<pre> |
||
<?xml version="1.0" encoding="UTF-8"?> |
|||
package games.stendhal.server.maps.myarea.mylocation; |
|||
<zones> |
|||
<!-- |
|||
** Load zones. Written from left to right and from top to bottom. |
|||
** Please respect it! |
|||
--> |
|||
</zones> |
|||
import java.util.Map; |
|||
import games.stendhal.server.StendhalRPZone; |
|||
import games.stendhal.server.maps.ZoneConfigurator; |
|||
public class IL0_MyNPC implements ZoneConfigurator |
|||
{ |
|||
/** |
|||
* Configure a zone. |
|||
* |
|||
* @param zone The zone to be configured. |
|||
* @param attributes Configuration attributes. |
|||
*/ |
|||
public void configureZone(StendhalRPZone zone, Map<String, String> attributes) { |
|||
// Add/configure entity to "zone", using optional configuration "attributes" |
|||
} |
|||
} |
|||
</pre> |
</pre> |
||
Then edit the file '''data/conf/zones.xml''' and add a relevant entry (in alphabetical order for normal areas): |
|||
<pre> |
<pre> |
||
<group uri="zones/<area>.xml"/> |
|||
<zone name="int_myarea_mylocation" file="int_myarea_mylocation.xstend"/> |
|||
</pre> |
</pre> |
||
To enable a zone in the server, edit the file '''data/conf/zones/<area>.xml''' and add an entry (in the appropriate level/top-down/left-right order), giving it the zone name and map tmx file to use: |
|||
If you have custom configuration code, add appropriete "<configurator>" entries in your "<zone>" element, using the fully qualified package/class name of your java classes: |
|||
<source lang="xml"> |
|||
<pre> |
|||
<zone name="int_myarea_mylocation" file=" |
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx"/> |
||
<zone name="0_myarea_mylocation" level="0" x="100000" y="200000" file="Level 0/myarea/mylocation.tmx"/> |
|||
</source> |
|||
In the case of non-interior zones, the level and x/y coordinate should also be included in the <zone> element (setting them in the tmx file has been deprecated). For interior zones, the level xml attribute should '''not''' be set (for now). The coordinate starts at the top-left corner, and should align against (but never overlap) other zones in the same level. |
|||
If the new zone is outside, or otherwise should follow the normal daylight cycle, add a coloring method definition to it, like this: |
|||
<source lang="xml"> |
|||
<zone name="0_myarea_mylocation" level="0" x="100000" y="200000" file="Level 0/myarea/mylocation.tmx"> |
|||
<attributes> |
|||
<parameter name="color_method">time</parameter> |
|||
</attributes> |
|||
</zone> |
</zone> |
||
</ |
</source> |
||
About other possible coloring methods for maps, see [[LightsAndColor | Lights and Color]]. |
|||
Most zones can be configured just using this xml file. However, there are currently some things, such as NPC's that need special handling. If you need to do custom zone configuration, create one or more new java source file(s) at '''src/games/stendhal/server/maps/<area>/<base-location>/<entity>.java'''. The '''<area>/<base-location>''' path would essentially be the same as your '''.tmx''' file uses. In case where locations have been split due to size (like _nw, _ne, _s, _n, etc), only the base location name is used. |
|||
Ideally this would be one file per independant entity created (so they can be enabled/disabled separately). |
|||
Some (ficticious) examples for the new convention of tmx path to java filename are: |
|||
interiors/orril/old_cabin.tmx -> .../maps/orril/old_cabin/HermitNPC.java |
|||
Level 0/ados/rock.tmx -> .../maps/ados/rock/NomadNPC.java |
|||
Level -1/ados/caves_e.tmx -> .../maps/ados/caves/CaveinTrigger.java |
|||
Level 0/nalwor/river_se.tmx -> .../maps/nalwor/river/FishermanNPC.java |
|||
Level 0/nalwor/river_se.tmx -> .../maps/nalwor/river/AdventurerNPC.java |
|||
Level 0/nalwor/river_sw.tmx -> .../maps/nalwor/river/CamperNPC.java |
|||
Level 0/semos/forest_n.tmx -> .../maps/semos/forest/LumberjackNPC.java |
|||
Open the file and make sure that it looks like this: |
|||
<source lang="java"> |
|||
package games.stendhal.server.maps.myarea.mylocation; |
|||
import java.util.Map; |
|||
import games.stendhal.server.StendhalRPZone; |
|||
import games.stendhal.server.config.ZoneConfigurator; |
|||
public class MyEntity implements ZoneConfigurator { |
|||
/** |
|||
* Configure a zone. |
|||
* |
|||
* @param zone The zone to be configured. |
|||
* @param attributes Configuration attributes. |
|||
*/ |
|||
public void configureZone(StendhalRPZone zone, Map<String, String> attributes) { |
|||
// Add/configure entity to "zone", using optional configuration "attributes" |
|||
} |
|||
} |
|||
</source> |
|||
For each custom configuration code class, add appropriate "<configurator>" entries in your "<zone>" element, using the fully qualified package/class name of your java classes: |
|||
<source lang="xml"> |
|||
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx"> |
|||
<configurator class-name="games.stendhal.server.maps.myarea.mylocation.MyEntity"/> |
|||
</zone> |
|||
</source> |
|||
Now once it is added, test the result by starting server. |
Now once it is added, test the result by starting server. |
||
= Populating zones = |
= Populating zones = |
||
Now open again the |
Now open again the MyEntity.java file and let's start adding code to '''configureZone()''', or a method called by it. Most usual things we are going to add to a zone are NPC, and special items. |
||
== Adding Items == |
== Adding Items == |
||
| Line 72: | Line 112: | ||
There are several types of portals: |
There are several types of portals: |
||
* Portal |
* Portal ''added using xml'' |
||
* One way portal |
* One way portal ''added using xml'' |
||
* Stairs portals |
* Stairs portals ''added using tiled'' |
||
* House Door portals |
* House Door portals ''added using tiled'' |
||
A portal is just the generic portal. It works for almost everything you can imagine. |
A portal is just the generic portal. It works for almost everything you can imagine. |
||
Portals are created by adding a entries to your zone in '''zones.xml'''. For example creating a portal to an internal building entrance might look like: |
Portals are created by adding a entries to your zone in '''zones.xml'''. For example creating a portal to an internal building entrance which is at 1 12 inside the building (and the outer entrance to go in is at 10 15) might look like: |
||
<source lang="xml"> |
|||
<pre> |
|||
<zone name="int_myarea_mylocation" file=" |
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx"> |
||
<portal x=" |
<portal x="1" y="12" ref="entrance"> |
||
<destination zone="0_myarea_city" ref="mylocation_entrance"/> |
<destination zone="0_myarea_city" ref="mylocation_entrance"/> |
||
</portal> |
</portal> |
||
</zone> |
</zone> |
||
<zone name="0_myarea_city" file=" |
<zone name="0_myarea_city" Level="0" x="500000" y="500000" file="Level 0/myarea/city.tmx"> |
||
<portal x="10" y="15" ref="mylocation_entrance"> |
<portal x="10" y="15" ref="mylocation_entrance"> |
||
<destination zone="int_myarea_location" ref="entrance"/> |
<destination zone="int_myarea_location" ref="entrance"/> |
||
</portal> |
</portal> |
||
</zone> |
</zone> |
||
</ |
</source> |
||
The '''ref''' attribute of a portal should be a name unique to the zone it is in (and meaningful). This value has a corresponding reference via the '''<destination>''' ref name. You are responsible for correctly assigning the ref names of each portal. |
The '''ref''' attribute of a portal should be a name unique to the zone it is in (and meaningful). This value has a corresponding reference via the '''<destination>''' ref name. You are responsible for correctly assigning the ref names of each portal. |
||
| Line 99: | Line 139: | ||
A one way portal is a portal that only exists as endpoint, so none can use the portal to move back to the origin. For one way portals, there is no '''<destination>''' sub-element, as they don't go anywhere. Also, you need to provide a non-default implementation: |
A one way portal is a portal that only exists as endpoint, so none can use the portal to move back to the origin. For one way portals, there is no '''<destination>''' sub-element, as they don't go anywhere. Also, you need to provide a non-default implementation: |
||
<source lang="xml"> |
|||
<pre> |
|||
<portal x="11" y="44" ref="my_exit"> |
<portal x="11" y="44" ref="my_exit"> |
||
<implementation class-name="games.stendhal.server.entity.portal.OneWayPortalDestination"/> |
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination"/> |
||
</portal> |
</portal> |
||
</ |
</source> |
||
The House door portal is a special type of portal that automatically creates all the portals and areas needed to add a house to that zone with its entrance on point where the portal is. |
The House door portal is a special type of portal that automatically creates all the portals and areas needed to add a house to that zone with its entrance on point where the portal is. In tiled/tileset/logic/portals.png it's the one with the door on it. Add it to the 'city' type map where you want the house entrance. Please see [[HowToUseTiledToCreateStendhalMaps2#Objects_revisited|the tiled tutorial]]. |
||
Finally the stairs portals also automate the creation of stairs between two areas. It is very important that the portals ( both ends ) are exactly on the same position but on different levels. Position means absolute position. Also, due to current implementation, be careful '''not''' to place omni-directional stair portals at the same exact location between adjacent levels if they're not meant to be linked, as they might inadvertantly be linked. Directional stairs are safer and only link with the level they go toward. |
Finally the stairs portals also automate the creation of stairs between two areas. It is very important that the portals ( both ends ) are exactly on the same position but on different levels. Position means absolute position. Also, due to current implementation, be careful '''not''' to place omni-directional stair portals at the same exact location between adjacent levels if they're not meant to be linked, as they might inadvertantly be linked. Directional stairs are safer and only link with the level they go toward. The [[HowToUseTiledToCreateStendhalMaps2#Objects_revisited|the tiled tutorial]] covers this in more detail. |
||
=== Condition and Action Portals === |
|||
== Adding NPC == |
|||
Portals are being refactored to allow combinations of conditions and actions in a very similar way to NPCs. In fact, you can use the same conditions and actions. |
|||
Usually we add NPC to make world more alive and to use them in Quests. It is because of that reason, that is so important that you add NPC on the zone they are. |
|||
The full list is found in http://arianne.cvs.sourceforge.net/arianne/stendhal/src/games/stendhal/server/entity/npc/action and http://arianne.cvs.sourceforge.net/arianne/stendhal/src/games/stendhal/server/entity/npc/condition |
|||
A portal which you can put a Condition and / or action to is called a ConditionAndActionPortal. You don't have to set both a condition and an action. |
|||
First, you should decide if you're going to use your NPC later in a quest. |
|||
Implement them like this: |
|||
''new SpeakerNPC()'' simply creates a new NPC that has dialogs but will not participate later on any particular quest. |
|||
<pre> |
|||
npc=new SpeakerNPC() |
|||
{ |
|||
<source lang="xml"> |
|||
}; |
|||
<portal x="64" y="117" ref="entrance"> |
|||
npc.setName("name"); |
|||
<destination zone="-1_semos_chasm_n" ref="exit" /> |
|||
</pre> |
|||
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal"> |
|||
<parameter name="condition">new PlayerHasItemWithHimCondition("special magical thingy", 10)</parameter> |
|||
<parameter name="action">new DropItemAction("special magical thingy", 10)</parameter> |
|||
<parameter name="rejected">You need 10 of the special magical thingies.</parameter> |
|||
</implementation> |
|||
</portal> |
|||
</source> |
|||
You can use NotConditions: |
|||
Notice that in this case, you have to specify the name later in ''npc.setName()'' |
|||
<source lang="xml"> |
|||
''npcs.add("name",new SpeakerNPC()...)'' creates also a new NPC '''and besides''' adds it to a global list so next time you need to get the NPC for participating in a quest you can call it by its ''name'' using ''npcs.get(name)'' |
|||
<portal x="65" y="13" ref="entrance"> |
|||
<pre> |
|||
<destination zone="-1_semos_chasm_w" ref="exit" /> |
|||
NPC npc=npcs.add("name",new SpeakerNPC() |
|||
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal"> |
|||
{ |
|||
<parameter name="condition">new NotCondition(new PlayerHasPetOrSheepCondition())</parameter> |
|||
<parameter name="rejected">To get into the evil chasm you must bring a sacrificial animal</parameter> |
|||
}); |
|||
</implementation> |
|||
</pre> |
|||
</portal> |
|||
</source> |
|||
You can do more than one action by using MultipleActions and list the actions for it, and combine Conditions with an AndCondition, listing the conditions for it. |
|||
Notice that in this case, the name is especified first in ''NPC npc=npcs.add("name",...'' |
|||
The syntax is slightly different than with NPCs, please note these extra [ ] surrounding the list. This is due to a bug in groovy. |
|||
<source lang="xml"> |
|||
<portal x="37" y="16" ref="example1"> |
|||
<destination zone="int_semos_zone" ref="choice_floor_1" /> |
|||
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal"> |
|||
<parameter name="condition">new AndCondition([new NotCondition(new PlayerHasItemWithHimCondition("claymore")) , new LevelLessThanCondition(100)])</parameter> |
|||
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("claymore")])</parameter> |
|||
</implementation> |
|||
</portal> |
|||
</source> |
|||
The destination settings and references are all as normal. You can still set other attributes like a reject message and hidden from minimap, as in some of the examples above. |
|||
In other words, ''new SpeakerNPC()'' creates just a new NPC of the class SpeakerNPC but with ''npcs.add("name",new SpeakerNPC()...)'' you are in fact extending SpeakerNPC to add new functionality. |
|||
== Adding NPCs== |
|||
See [[Stendhal NPC Coding]] |
|||
In this case, let's suppose you plan on using our NPC later in a quest, so use something like: |
|||
Congrats you have populated your new zone. |
|||
<pre> |
|||
SpeakerNPC npc=npcs.add("Ilisa",new SpeakerNPC() |
|||
{ |
|||
protected void createPath() |
|||
{ |
|||
List<Path.Node> nodes=new LinkedList<Path.Node>(); |
|||
nodes.add(new Path.Node(9,5)); |
|||
nodes.add(new Path.Node(14,5)); |
|||
setPath(nodes,true); |
|||
} |
|||
protected void createDialog() |
|||
{ |
|||
Behaviours.addGreeting(this); |
|||
Behaviours.addJob(this, "I have healing abilities and I heal wounded players. I also sell potions and antidotes."); |
|||
Behaviours.addHelp(this, "Ask me to #heal you and I will help you or ask me #offer and I will show my shop's stuff."); |
|||
Behaviours.addSeller(this, new Behaviours.SellerBehaviour(shops.get("healing"))); |
|||
Behaviours.addHealer(this, 0); |
|||
Behaviours.addGoodbye(this); |
|||
} |
|||
}); |
|||
zone.assignRPObjectID(npc); |
|||
npc.put("class","welcomernpc"); |
|||
npc.set(9,5); |
|||
npc.initHP(100); |
|||
zone.addNPC(npc); |
|||
</pre> |
|||
Use '''npcs.add()''' as this way the NPC is added to a list of NPC from where you can later obtain it for adding more dialogues for quests. Make sure the name you give to your NPC is unique. |
|||
Just after that it is a good idea to create a path that the NPC will follow on that area. |
|||
And then create a dialog. Dialogs and such are explained in Quest sections. |
|||
Now simply assign an id to the npc, set its outfit either by: |
|||
* setting its class to a PNG image that exists at ''data/sprites/npc'' |
|||
* setting its outfit with setOutfit method. |
|||
See [[StendhalOpenTasks#Player's outfits| How to know player's outfits specifications]] |
|||
Finally set its initial position and its HP. Don't worry for your NPC. It can't be attacked nor killed. |
|||
Once that is done add the NPC to zone using ''zone.addNPC()'' method. |
|||
Congrats you have populated your new zone. |
|||
[[Stendhal|Back to the Stendhal main page]] |
|||
[[Stendhal |
[[Category:Stendhal]] |
||
Latest revision as of 14:26, 26 March 2016
Of course you have already read:
Ok, and I assume that you can write or at least read xml.
Modify world.tmx
Now make sure if your map is new that world.tmx shows it by adding a new tileset with your map image. This step is just for your mental wellness. Stendhal doesn't use world.tmx.
Create a map file
If you are adding a zone for a new major area, create the file data/conf/zones/<area>.xml with the following:
<?xml version="1.0" encoding="UTF-8"?> <zones> <!-- ** Load zones. Written from left to right and from top to bottom. ** Please respect it! --> </zones>
Then edit the file data/conf/zones.xml and add a relevant entry (in alphabetical order for normal areas):
<group uri="zones/<area>.xml"/>
To enable a zone in the server, edit the file data/conf/zones/<area>.xml and add an entry (in the appropriate level/top-down/left-right order), giving it the zone name and map tmx file to use:
<source lang="xml">
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx"/> <zone name="0_myarea_mylocation" level="0" x="100000" y="200000" file="Level 0/myarea/mylocation.tmx"/>
</source>
In the case of non-interior zones, the level and x/y coordinate should also be included in the <zone> element (setting them in the tmx file has been deprecated). For interior zones, the level xml attribute should not be set (for now). The coordinate starts at the top-left corner, and should align against (but never overlap) other zones in the same level.
If the new zone is outside, or otherwise should follow the normal daylight cycle, add a coloring method definition to it, like this:
<source lang="xml">
<zone name="0_myarea_mylocation" level="0" x="100000" y="200000" file="Level 0/myarea/mylocation.tmx"> <attributes> <parameter name="color_method">time</parameter> </attributes> </zone>
</source>
About other possible coloring methods for maps, see Lights and Color.
Most zones can be configured just using this xml file. However, there are currently some things, such as NPC's that need special handling. If you need to do custom zone configuration, create one or more new java source file(s) at src/games/stendhal/server/maps/<area>/<base-location>/<entity>.java. The <area>/<base-location> path would essentially be the same as your .tmx file uses. In case where locations have been split due to size (like _nw, _ne, _s, _n, etc), only the base location name is used.
Ideally this would be one file per independant entity created (so they can be enabled/disabled separately).
Some (ficticious) examples for the new convention of tmx path to java filename are:
interiors/orril/old_cabin.tmx -> .../maps/orril/old_cabin/HermitNPC.java Level 0/ados/rock.tmx -> .../maps/ados/rock/NomadNPC.java Level -1/ados/caves_e.tmx -> .../maps/ados/caves/CaveinTrigger.java Level 0/nalwor/river_se.tmx -> .../maps/nalwor/river/FishermanNPC.java Level 0/nalwor/river_se.tmx -> .../maps/nalwor/river/AdventurerNPC.java Level 0/nalwor/river_sw.tmx -> .../maps/nalwor/river/CamperNPC.java Level 0/semos/forest_n.tmx -> .../maps/semos/forest/LumberjackNPC.java
Open the file and make sure that it looks like this:
<source lang="java"> package games.stendhal.server.maps.myarea.mylocation;
import java.util.Map; import games.stendhal.server.StendhalRPZone; import games.stendhal.server.config.ZoneConfigurator;
public class MyEntity implements ZoneConfigurator {
/**
* Configure a zone.
*
* @param zone The zone to be configured.
* @param attributes Configuration attributes.
*/
public void configureZone(StendhalRPZone zone, Map<String, String> attributes) {
// Add/configure entity to "zone", using optional configuration "attributes"
}
} </source>
For each custom configuration code class, add appropriate "<configurator>" entries in your "<zone>" element, using the fully qualified package/class name of your java classes:
<source lang="xml">
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx"> <configurator class-name="games.stendhal.server.maps.myarea.mylocation.MyEntity"/> </zone>
</source>
Now once it is added, test the result by starting server.
Populating zones
Now open again the MyEntity.java file and let's start adding code to configureZone(), or a method called by it. Most usual things we are going to add to a zone are NPC, and special items.
Adding Items
See How to add items to Stendhal and How to know graphics specifications
Adding Portals
A portal is a door to another place. It can be used to go up and down stairs, or to teleport player to other places or simply to enter a building. Whenever you encounter something that engine challenges you about how to do ( for example cross under a brigde or pass under a castle door ) you can solve it using portals.
There are several types of portals:
- Portal added using xml
- One way portal added using xml
- Stairs portals added using tiled
- House Door portals added using tiled
A portal is just the generic portal. It works for almost everything you can imagine.
Portals are created by adding a entries to your zone in zones.xml. For example creating a portal to an internal building entrance which is at 1 12 inside the building (and the outer entrance to go in is at 10 15) might look like:
<source lang="xml">
<zone name="int_myarea_mylocation" file="interiors/myarea/mylocation.tmx">
<portal x="1" y="12" ref="entrance">
<destination zone="0_myarea_city" ref="mylocation_entrance"/>
</portal>
</zone>
<zone name="0_myarea_city" Level="0" x="500000" y="500000" file="Level 0/myarea/city.tmx">
<portal x="10" y="15" ref="mylocation_entrance">
<destination zone="int_myarea_location" ref="entrance"/>
</portal>
</zone>
</source>
The ref attribute of a portal should be a name unique to the zone it is in (and meaningful). This value has a corresponding reference via the <destination> ref name. You are responsible for correctly assigning the ref names of each portal.
A one way portal is a portal that only exists as endpoint, so none can use the portal to move back to the origin. For one way portals, there is no <destination> sub-element, as they don't go anywhere. Also, you need to provide a non-default implementation:
<source lang="xml">
<portal x="11" y="44" ref="my_exit"> <implementation class-name="games.stendhal.server.entity.mapstuff.portal.OneWayPortalDestination"/> </portal>
</source>
The House door portal is a special type of portal that automatically creates all the portals and areas needed to add a house to that zone with its entrance on point where the portal is. In tiled/tileset/logic/portals.png it's the one with the door on it. Add it to the 'city' type map where you want the house entrance. Please see the tiled tutorial.
Finally the stairs portals also automate the creation of stairs between two areas. It is very important that the portals ( both ends ) are exactly on the same position but on different levels. Position means absolute position. Also, due to current implementation, be careful not to place omni-directional stair portals at the same exact location between adjacent levels if they're not meant to be linked, as they might inadvertantly be linked. Directional stairs are safer and only link with the level they go toward. The the tiled tutorial covers this in more detail.
Condition and Action Portals
Portals are being refactored to allow combinations of conditions and actions in a very similar way to NPCs. In fact, you can use the same conditions and actions. The full list is found in http://arianne.cvs.sourceforge.net/arianne/stendhal/src/games/stendhal/server/entity/npc/action and http://arianne.cvs.sourceforge.net/arianne/stendhal/src/games/stendhal/server/entity/npc/condition
A portal which you can put a Condition and / or action to is called a ConditionAndActionPortal. You don't have to set both a condition and an action.
Implement them like this:
<source lang="xml">
<portal x="64" y="117" ref="entrance">
<destination zone="-1_semos_chasm_n" ref="exit" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new PlayerHasItemWithHimCondition("special magical thingy", 10)</parameter>
<parameter name="action">new DropItemAction("special magical thingy", 10)</parameter>
<parameter name="rejected">You need 10 of the special magical thingies.</parameter>
</implementation>
</portal>
</source>
You can use NotConditions:
<source lang="xml">
<portal x="65" y="13" ref="entrance"> <destination zone="-1_semos_chasm_w" ref="exit" /> <implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal"> <parameter name="condition">new NotCondition(new PlayerHasPetOrSheepCondition())</parameter> <parameter name="rejected">To get into the evil chasm you must bring a sacrificial animal</parameter> </implementation> </portal>
</source>
You can do more than one action by using MultipleActions and list the actions for it, and combine Conditions with an AndCondition, listing the conditions for it. The syntax is slightly different than with NPCs, please note these extra [ ] surrounding the list. This is due to a bug in groovy.
<source lang="xml">
<portal x="37" y="16" ref="example1">
<destination zone="int_semos_zone" ref="choice_floor_1" />
<implementation class-name="games.stendhal.server.entity.mapstuff.portal.ConditionAndActionPortal">
<parameter name="condition">new AndCondition([new NotCondition(new PlayerHasItemWithHimCondition("claymore")) , new LevelLessThanCondition(100)])</parameter>
<parameter name="action">new MultipleActions([new IncreaseXPAction(100), new EquipItemAction("claymore")])</parameter>
</implementation>
</portal>
</source>
The destination settings and references are all as normal. You can still set other attributes like a reject message and hidden from minimap, as in some of the examples above.
Adding NPCs
Congrats you have populated your new zone.