Modding 101 - For Beginners

Discussion forum for Devil Whiskey 3rd Party MODS.

Moderator: Admin

User avatar
Growler
Necrolord
Posts: 1740
Joined: Mon Feb 14, 2005 10:37 pm
Location: Sputnik
Contact:

Post by Growler »

How's this look?
Well, except for the 3 items enveloped by ?-marks..which I hope someone can shed light on?
Btw, not always sure whether a null/zero/0 needs to be included in some of the lines?

MainConfigFile.cfg (file below)
allcell.cfg
allwall.cfg
TESTCELLmon.cfg ('dummy/empty' monster file)

Code: Select all

#   Want a 8 x 8 map = 20x20 with buffer added

TestMap 20 20  ?default floor&ceiling--ok to leave blank?  DW Title Bar.JPG

allwall.cfg  allcell.cfg   ?events?   TESTCELLmon.cfg

SPECLITS 0 0 0 0 .8 .8 .8

audio/config 1
DwarfCaves.dat 0

SPECCELL 10 10 0

RANDITEMS 0

10 10 <--&#123;is this where u usually start w/ 10, 10 ?&#125;  ?=cell name?
sorry if the extra #-signs are annoying--but they sho' hep me keep it separated!
No Contraries : No Progression.
Opposition is true friendship, unless one is opposed to true friendship or (try) Resisting here http://www.cafepress.com/notheresistor
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

A few things.

1. To the best of my knowledge, you can not leave the default floor and ceiling blank.
2. For the events file, you can put the name in for now (ie Testevents.cfg"
3. You can, however, put NULL for the title bar image.
4. For the Special lights, it should be SPECLITE, not SPECLITS. Not sure how it came out that way in my post. Also, those values must be 0.0 and 0.8

Other than that, it looks good. I will give you a little more time to make these edits before I really go into the events files.
User avatar
Growler
Necrolord
Posts: 1740
Joined: Mon Feb 14, 2005 10:37 pm
Location: Sputnik
Contact:

Post by Growler »

{edited code after SK's post below}
Decided to make a tiny map--2x2--for testing purps..
Image

Code: Select all

#   Want a 2 x 2 map &#40;20x20 with buffer added&#41;

TestMap 20 20  pics/walls/cave_floor.dat  pics/walls/cave_ceil.dat   pics/other/DW_Title_Bar.JPG

maps/allwall.cfg  maps/allcell.cfg  maps/Testevents.cfg  maps/TESTCELLmon.cfg

SPECLITE  0.0  0.0  0.0  0.0  0.8  0.8  0.8

audio/config 1
DwarfCaves.dat 0

SPECCELL 11 11 0

RANDITEMS 0

11 10  Nwall
12 10  Nwall

10 11  Ewall
11 11  Nwall
12 11  DoorNwallE

10 12  Ewall
11 12  DoorEwallN
12 12  NEwall
so if a 2x2 map requires 8 cells defined, then a 3x3 map needs 15 cell defs..&
7x7 --> 63
8x8 --> 80
10x10 -> 121
20x20 --> 440 cells defined!

Formula appears to be (where X & Y are your map's basic dimensions)
(X*Y) + (X+Y)

gotta be some way to automate this process...so that if you have your map 'drawn out' (say, in a spreadsheet or ??) then these 'cell def' values can be auto-out-putted.. :D
Last edited by Growler on Thu Mar 24, 2005 3:29 pm, edited 1 time in total.
No Contraries : No Progression.
Opposition is true friendship, unless one is opposed to true friendship or (try) Resisting here http://www.cafepress.com/notheresistor
User avatar
ShadoKnight
Nomad
Posts: 28
Joined: Mon Mar 21, 2005 2:05 pm

Lots of info

Post by ShadoKnight »

This is a pretty long response, addressing a number of questions here. I'm taking them (mostly) in reverse order (since that's the order the little topic review window is in ;-) )....

First, someone commented that if you only define N and E (or any two non-opposing sides), you *must* have at least one square border. This is true, but it's also true that it's better to have at least one square border anyway - while it's technically possible to have things work right up to the edge, there are a couple corner cases where the code may not behave quite correctly, and it's easy to have a bug and not find it. Having 10 squares around the edge may be a little excessive - but probably not an issue on modern PCs. The bigger your map, the more memory it will require, and the more polygons will be drawn (though we're not talking huge poly counts anyway). Anything up to 1000x1000 should be very easily handled by any semi-modern PC.

As for floor and ceiling texture - you *MUST* point to a valid texture for the floor, the ceiling may be 'NULL', in which case you get no ceiling (you get sky, such as in Rennibister). You cannot leave either blank, as the parser is position-based and requires at least name, x, y, and floor (if you want a title bar, you *MUST* put something for ceiling). Also, I notice your title bar file name has spaces in it - this won't work (it will interpret this as a set of keywords, ignoring the last ones and trying to open a file 'DW' for the title bar). Spaces in filenames are broken anyway - don't do it ;-)

As for spacing in the cell listing - you can add blank lines or comment lines between cell definitions (IIRC - at one point you couldn't, but I'm fairly sure I added blank-line skipping to the map file parser), and within a cell definition you can add any non-newline whitespace between fields (i.e., spaces or tabs). That's it, though.

As to fonts - I don't remember which font we used on the title bars, but the font in the game is a hand-generated bitmap font, so you won't be able to match it exactly. That's why there's no descenders ;-)

As far as I remember, there is no limit on how many trap scripts can be written, really, it's just that it uses a %04d as the format specifier when loading the file.... in any case, you can at least get up to 9999 trap scripts, but remember, each one can be used more than once - you only need a new script for a new effect, not for a new instance of the same effect.

There's no built-in mechanism to handle one-way doors. It's not impossible to add to the code, but since I'm no longer part of Shifting Suns, I won't be doing it and I can't comment on whether or not they will. I *think* you could implement one-way doors using scripts, but I'll have to think about it....

As for secret doors, there's nothing special here, except that they're doors (i.e., walls with collision set to 0) that also have type 1 so spells can detect them (Origen already talked about that a little bit).

Cell types are a little off in Origen's description - there are actually 5 cell types. The default cell type, '0', is a standard cell. Cell type 1 is a cell with a special floor and/or garnish that can be entered by the party (i.e., the bushes in Rennibister, which have garnishes (the bushes), but can be walked in, or just about anywhere with a special floor). Cell type 2 is a cell with a special floor and/or garnish that cannot be entered by the party. Cell type 3 is a cell with a special floor and/or garnish, that is a non-standard height, that can be entered by the party. Height, for a cell, you ask? Well, if you have non-standard height walls in a dungeon, and you want the ceiling to also be higher than 1 unit up, you need a non-standard height cell. Cell type 4 is to 3 as 2 is to 1 (that is, cell with floor and/or garnish and non-standard height that cannot be entered - think a grand column in a giant underground dwarven city....). For cell types 3 and 4, there's an additional field at the end, <height>, which is 1-4 (just as for walls).

One last comment - someone asked about gateways and such in a city, and the answer they gave is exactly right - you simply provide a 'door' with a texture that has a large transparent area. Not only should that do the right thing as far as visibility, but it should also do the right thing with regards to shadows ;-).

SK
User avatar
HGamer
War Monger
Posts: 188
Joined: Thu Feb 10, 2005 7:59 pm
Location: Land of fruits & nuts, i.e. SoCal
Contact:

Post by HGamer »

Wow :D
Lots of info there!

Growler, you don't end up defining ALL the cells in the map. At least, not usually. Only cells that have at least one wall or door in one of the directions that you're using, or need something besides the default ceiling and floor. For instance, the 10 by 10 "buffer" doesn't need cell definitions except where there's a wall around the whole dungeon. And then only on the sides that really need it, so only for the x=10 row & y=10 column cells that are next to the other dungeon map cells.
The formula is more like (# of horizontal cells in dungeon +1)*(# of vertical cells in dungeon +1) - (# of cells that don't need a cell definition).
I hope that made sense...
1 point 21 jigawatts!
User avatar
Growler
Necrolord
Posts: 1740
Joined: Mon Feb 14, 2005 10:37 pm
Location: Sputnik
Contact:

Post by Growler »

Thanks guys for all the pointers, tips, hints, helps & quips! :P

Some of SK's more technical info sailed over my pate, but suspect it'll prove very helpful as the hazy path ahead crystalizes...

HGamer, I might have to challenge ya on the formula! :wink:
(only to see if I'm missing something)
See your point re: not defining any basic 'open/unbound' cells, thus needing to subtract those unnecessary cells...but still seems the first part of the formula should be:
(X*Y) + (X+Y) rather than (X+1)(Y+1)

let's assume all cells need to be defined for a 3x3 map which ='s 9 'primary/interior' cells + 3 ajacent cells to the left of map (for defining the outer left perimeter) + 3 ajacent cells to bottom of map (for defining the outer lower perimeter), so 9+3+3=15, right?
And the formula (X*Y) + (X+Y) yields 15.
(3x3)+(3+3)=9+6=15

But if we use the (X+1)(Y+1) formula, we get 16.. (3+1)(3+1)=4x4=16

Then, as you say, we'd need to subtract any unnecessary cell defs...
-------
This may be a clumsy way to do a 1-way door, but how 'bout if you make 2 identical maps (except for any 1-way doors!), then anytime you pass thru a 1-wayer a script? switches ya to the Other map (which is same except now the door you just passed thru has been replaced by a solid wall...but this may be harder to implement than I'm thinking possibly due to tracking stuff in each map??
No Contraries : No Progression.
Opposition is true friendship, unless one is opposed to true friendship or (try) Resisting here http://www.cafepress.com/notheresistor
User avatar
ShadoKnight
Nomad
Posts: 28
Joined: Mon Mar 21, 2005 2:05 pm

Post by ShadoKnight »

While that could work (i.e., achieve the desired effect), there are a couple flaws:

1) Load time - you'd have to switch maps when you walk through the door, which is noticeable to the user
2) Automap - it wouldn't keep up (you're on a new map, so the old automap info wouldn't be there).

What I'm thinking is a creative use of scripting - you'd put scripts on all the squares around the one-way door - not just immediately to either side, but also all squares leading into those immediate neighbors. Then, you can figure out where you're coming from, and if you're supposed to be allowed through the door (similar to performing the collision computation yourself). It'd be kludgy in scripting, but I think it would give the cleanest user exprience....

Maybe, if I get adventurous, I'll hack up a one-way door example level and patch to put it in Rennibister somewhere.... we'll see ;-).

SK
User avatar
HGamer
War Monger
Posts: 188
Joined: Thu Feb 10, 2005 7:59 pm
Location: Land of fruits & nuts, i.e. SoCal
Contact:

Post by HGamer »

I coded a one-way wall by putting an event with a teleport in the cell on the far side of the wall-that-supposedly-just-appeared-behind-the-party. Teleport script just sends you to a new part of the map. Unfortunately, this messes up the automap, and complicates map coding. Also need more teleports to get back to the rest of the level unless the one-way is basically into a large trap.
When Origen gets into wraparound magic, this should make more sense as it's the same principle.

If you can get the DW engine to tell you where the party came from, or at least which way they're currently facing, SK's way of scripting a one-way door or wall could work. I didn't know that you could get that information though. The best that I know of at present is to figure out from setting user flags in nearby cells and looking at lflagS values to determine the party's current location. Facing doesn't seem accessible except as a write-only via setExit(). But I await the words of the master in the hopes of attaining wisdom. (really, I do!)
Perhaps this deserves its own thread, so we don't clutter Origen's tutorial prose.
1 point 21 jigawatts!
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

Well, I am not sure how far along Growler is, but lets move on to the last cfg file of MOD creation: the events file.

The events file itself is fairly simple, but is by far the most importsnt. This file is what determins what will happen in your maps. Everything from Entry and Exit stairs to chests, to scripted battles, to messages, and everything in between is defined in this map. For each event, you need the following information:

Code: Select all

<trigger X> <trigger Y> <event processor>
<rebound X> <rebound Y> <rebound face angle> <script name>
The first line is the location where this event will take place. The first 2 are the X and Y coordinates on the map. The third value, known as the event processor, will usually be 2000. This means that the game will use the python interpreter that handles scripts. There are also some standard defined event processors, which require no additional efforts on your part. They are:

Code: Select all

1000 - Adventurers Hall
1001 - Elium's Energies
1002 - Temple of the Redeemer
1003 - Collegium of Magika
1005 - Order of the Lyre
1006 - Melkoran's Tavern
1007 - The Green Bard
1008 - Hughter's Owl
1009 - The Chiccasaw
1010 - The Marauder's Hole
1011 - Starfire Swords
1012 - Imperial Weapons
1013 - Arms of Valor
1014 - General Store
1017 - Landru's Craft Supply
1018 - Guard's Barracks &#40;However, most barracks in the game are scripted&#41;
1022 - Casimo
1023 - Arcanium
1050 - Generic Stranger's House
2000 - Python Interpreter for python scripts
The second line includes the rebound location (X and Y coordinates, as well as the face angle, or direction the party will be facing). This is used if the script terminates with a false (0) result. An example of this is when a person enters a house, they will be "rebounded" back outside when the script terminates. The Face Angle is represented as either 0 (North), 90 (West), 180 (South), or 270 (East)

The final parameter, known as script name, is the exact name of the .py file that is located in your data>scripts folder, although you will not put the .py extension. So, if you are calling a script called ExitStairs.py, you would put ExitStairs for the script name.

Here is an example of an event file:

Code: Select all

10 10 2000
11 10 270 ExitStairs
This will call for a script names ExitStairs, which will be called when the party enters the location 10, 10. If the script returns a false value (the party does not take the stairs), they will be rebounded to 11, 10, and facing East (270).
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

Okay. So now we have some basics on the events file, so we need to define two seperate events. The first event is an entry location, so we can enter our map. The second event is an exit location, where we can exit our map.

Here is a simple example of an entry script:

Code: Select all


from eventAPI import *
from APIUtils import *

def fireEvent&#40;e&#41;&#58;
    showPicture&#40;e, "Palace"&#41;
    if &#40;poseYesNo&#40;e,
        &#91;"Will you enter through this mysterious doorway?"&#93;&#41;&#41;&#58;
        tickGame&#40;e, 60&#41;
        setExit&#40;e, "maps/dkjail.cfg", 11, 15, 270&#41;
    return 0
All you need to edit on this is the name of the map file (dkjail.cfg), as well as the entry location in your map (11, 15) and the direction you would be facing (270)

A simple example of an exit script is:

Code: Select all

#Default Exit
from eventAPI import showPicture, tickGame, setExit
from APIUtils import poseYesNo

def fireEvent&#40;e&#41;&#58;
    showPicture&#40;e, "Palace"&#41;
    if &#40;poseYesNo&#40;e,
        &#91;"There is a door here, leading out into Rennibister.",
         "Do you leave?"&#93;&#41;&#41;&#58;
        tickGame&#40;e, 60&#41;
        setExit&#40;e, "maps/renibister.cfg", 21, 28, 90&#41;
    return 0


This will leave you right outside of the house that can be used as the cheaters stronghold. I usually test all of my maps out at that location. There does not need to be anything changed in this script.

Now, we have to make these two scripts accessable from the game. First, in your maps events file, you need to define your exit stairs event. You can refer to the previous post if you are having difficulties.

Next, you need to define your entry stairs in the renevents.cfg file. All you have to do is change lines 27-30. For lines 27 and 28, you need to put a # at the beginning of each of these lines.

For lines 29 and 30, you first need to remove the # sign from both of these lines, and then you need to replace the work cheat with the name of your entry stairs script. It should look something like this:

Code: Select all

#22 28 1050 1

22 28 2000 1
21 28 90 EntryStairs
We are now ready to test our map!
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

A few tips on testing your map.

1. Create a new game and start your testing with a new party.
2. First, walk up to the cell that you will be using as your test point, and save your game before you proceed.
3. If the game crashes, take note of when the game crashes. It may help you determine what went wront.

There is usually something that will go wrong the first try. So don't be discouraged if the game crashes to desktop when you try to enter. It usually takes a few tries before you get it right. Since everything is text based, 1 small punctuation mark or space that is in the wrong place will cause the game to crash.

So, did it work?

If so, then walk all over your map. Since we have not defined any scripts, traps, or monster encounters, it should allow you the freedom to make sure that everything looks as you want it. If there is anything you don't like, this is the time to change it.

Let me know how this goes, and then we will get to the more complicated stuff.
User avatar
Growler
Necrolord
Posts: 1740
Joined: Mon Feb 14, 2005 10:37 pm
Location: Sputnik
Contact:

Post by Growler »

Since my modest effort is failing miserably (when I attempt to enter me modungeon the entire game window simply disappears), and I can't figure out what's wrong...figure I'll see if Origen is at fault! :twisted:

Q: why does your ex. of an Entry script lack several of the 'eventAPI & APIUtils' imports that Are found in your ex. of an Exit script?

First few lines of your Entry script code are:

from eventAPI import *
from APIUtils import *

versus your Exit script beginning with:

from eventAPI import showPicture, tickGame, setExit
from APIUtils import poseYesNo

-do the asterisks* following the 2 'import' lines indicate for ALL of the options (such as: showPicture, tickGame, setExit, & 'poseYesNo' ) to be 'imported'?
...like a wildcard*.* used for searches?

If so, then O-man is likely off-the-hook, slangily so...& I owe him a sorry so. :wink:
No Contraries : No Progression.
Opposition is true friendship, unless one is opposed to true friendship or (try) Resisting here http://www.cafepress.com/notheresistor
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

The * do include all of the possible parameters, so that is not the problem.

This first thing you should do is check your main cfg file for punctiation. Make sure it is exactly like the Cells file. Also, make sure that all of the cells you use in the main cfg file are defined in the cells file.
User avatar
Growler
Necrolord
Posts: 1740
Joined: Mon Feb 14, 2005 10:37 pm
Location: Sputnik
Contact:

Post by Growler »

Ok, apologies for doubting the validity & veracity of your Entry script.. :oops:

Think it may be screwing up when it tries to read the .jpg of my title image file...don't imagine the game engine can read a jpeg image...so reckon it's got to be converted to either .pic or .dat format, eh?

Gonna check some existing main config files for syntax &/or what files/types they're using...& try NULL instead for now.. :?
No Contraries : No Progression.
Opposition is true friendship, unless one is opposed to true friendship or (try) Resisting here http://www.cafepress.com/notheresistor
User avatar
origen
Dark Sidhe Lord
Posts: 903
Joined: Thu Feb 10, 2005 5:54 pm
Location: Secret League of Nirulat Headquarters
Contact:

Post by origen »

You are right that it can not read a jpg file. I will go into the creation of images later on, if you like. but for now, you may be better off using NULL.

If you are still having difficulties, post your files (or link it from your website) and I can take a look.
Post Reply