Index

QCS Described

The Quick Creation System (or QCS) is a series of commands and modules that lets you create rooms, objects, exits, and NPCs easily and quickly. Before the QCS, if you wanted to make an orc, you would edit the text file by hand, or copy a template file and use an editor to manually change the lines you needed to modify. This could be a tiresome process, as the standard editor can be a bit awkward, and making dozens of objects this way could be real torture for beginners.

The QCS changes all of that. Rather than use an editor to modify files, the QCS gives you commands that permit you to modify objects on the fly. This means that orc creation, for example, could involve just the following simple steps (please note "NPC" is another word for "Mob"):

And that's it. All your modifications automatically get written to new_orc.c (usually in your area directory), and you now have an npc you can add to a room. Adding things to rooms is just as easy. Creating weapons, armor, and other objects are done the same way. For complete details and examples, read the QCS chapters in the Creators Manual. The QCS section starts in chapter 31.

Example Log

Below you will find an excerpt from an short building session using Dead Souls. This should be more or less exactly what you'll see by entering the commands hilighted in red.


The first thing we need to do is get back to our personal work room. We can do this using the home command.

home
/realms/testycre/workroom
Testycre's workroom [e,d]
You are standing in the workroom of the mighty Testycre!
You may return to the Creators' Hall by going down.
A sample room is east.
There is a sign here you can read.
There is a sheet here you can read.
A wooden chest is here.

Next, we move east to a sample room that is created automatically for us. We'll be experimenting in here.

east
/realms/testycre/area/room/sample_room
Sample Room [e, w]
This is a room you can use as a template.
A simple table is here.
A fighter is standing here.

Room Creation (Back to Top)

This is the standard sample room. We're about to create a new room to the north of it via the create command.

create room north test1
It appears you have write access to this area.
It's a null mapping
Indenting file...
"/tmp/indent.1134436511.tmp.dat" 20 lines 330 bytes
Exit from ed.

You wave your hand, and a new exit appears.
You begin uttering a magical incantation.
Indenting file...
"/tmp/indent.1134436511.tmp.dat" 27 lines 543 bytes
Exit from ed.

Indenting file...
"/tmp/indent.1134436511.tmp.dat" 27 lines 544 bytes
Exit from ed.

We can now move east to our new room. Notice how it says it's a copy of our sample room.

n
/realms/testycre/area/room/test1
Copy of /realms/testycre/area/room/sample_room.c [s]
This is a room you can use as a template.
A simple table is here.
A fighter is standing here.

Now we'll change the short description to avoid confusion between our original sample room and the newly created one. Note that a room's short description appears as its title or name near the top of the text when a user looks at it.

modify here short Room One
Indenting file...
"/tmp/indent.1134436526.tmp.dat" 27 lines 515 bytes
Exit from ed.

We don't need the fighter from the other room here, so we remove him from this new room's inventory.

delete fighter
Indenting
file...
"/tmp/indent.1134436532.tmp.dat" 26 lines 507 bytes
Exit from ed.

/realms/testycre/area/room/test1: Ok
/realms/testycre/area/room/test1
Room One [w]
This is a room you can use as a template.
A simple table is here.

SetInventory modification complete.

Now we'll make another room.

create room east test2
It appears you have write access to this area.
It's a null mapping
Indenting file...
"/tmp/indent.1134436578.tmp.dat" 20 lines 324 bytes
Exit from ed.

You wave your hand, and a new exit appears.
You begin uttering a magical incantation.
Indenting file...
"/tmp/indent.1134436578.tmp.dat" 27 lines 557 bytes
Exit from ed.

Indenting file...
"/tmp/indent.1134436578.tmp.dat" 27 lines 525 bytes
Exit from ed.

We'll move east into the newly created room.

e
/realms/testycre/area/room/test2
Copy of /realms/testycre/area/room/test1.c [w]
This is a room you can use as a template.
A simple table is here.

Once again, we'll rename our new room.

modify here short Room 2
Indenting file...
"/tmp/indent.1134436590.tmp.dat" 26 lines 499 bytes
Exit from ed.

We can now set the room's long description. This will show up as the body of the room when a player types look.

modify here long This is the second test room.
Indenting file...
"/tmp/indent.1134436608.tmp.dat" 26 lines 487 bytes
Exit from ed.

We don't need that table here, let's delete it.

delete table
Indenting file...
"/tmp/indent.1134436612.tmp.dat" 25 lines 447 bytes
Exit from ed.

/realms/testycre/area/room/test2: Ok
/realms/testycre/area/room/test2
Room 2 [w]
This is the second test room.
SetInventory modification complete.

For the sake of self-assurance, we can look at the room's file to make sure that our modifications are actually being saved.

more here
#include <lib.h>
#include "/realms/testycre/customdefs.h"

inherit LIB_ROOM;

static void create() {
room::create();
SetClimate("indoors");
SetAmbientLight(30);
SetShort("Room 2");
SetLong("This is the second test room.");
SetExits(([
"west" : "/realms/testycre/area/room/test1",
]));

SetItems( ([
"template" : "That's what this is.",
]) );

SetInventory(([
]));
}

void init(){
::init();
}

NPC Creation (Back to Top)

Now we'll create a new NPC (Mob) called "guy". The file name will also be "guy".

create npc guy
I'm going to go with the appropriate area directory:
/realms/testycre/area/npc/guy.c
You wave your hand mysteriously and a generic npc materializes!

We can look at our new room and see the NPC standing there.

l
/realms/testycre/area/room/test2
Room 2 [w]
This is the second test room.
A generic npc is standing here.

The first thing to do is to rename the new NPC in order to avoid confusion. An NPC's name is what the lib refers to the NPC as.

modify npc name guy
Indenting file...
"/tmp/indent.1134436801.tmp.dat" 15 lines 417 bytes
Exit from ed.

We can now set one or more NPC aliases, called "ids". Note that in the following example, we enter three different ones, all of which point to the same NPC. A player could look at any of these IDs and get the NPC.

modify npc id
This setting takes multiple values. If you have no more values to
enter, then enter a dot on a blank line. To cancel, enter a single q on a blank
line.
You may now enter the next value. So far, it is blank.
If you're done entering values, enter a dot on a blank line.
dude You may now enter the next value. So far, we have: ({ "dude" }) If you're done entering values, enter a dot on a blank line. fellow You may now enter the next value. So far, we have: ({ "dude", "fellow" }) If you're done entering values, enter a dot on a blank line. fella You may now enter the next value. So far, we have: ({ "dude", "fellow", "fella" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "dude", "fellow", "fella" }) Indenting file... "/tmp/indent.1134436831.tmp.dat" 19 lines 442 bytes Exit from ed. /realms/testycre/tmp/guy1134436805: Ok /realms/testycre/area/npc/guy: Ok SetId modification complete.

Now we'll set the NPCs short description, or name. Any condition such as "is standing here" is appended to the end of the NPC's short description, so don't end it with a period or any other punctuation.

modify guy short The Dude
Indenting file...
"/tmp/indent.1134436855.tmp.dat" 19 lines 437 bytes
Exit from ed.

We'll set the long description. This is what is shown when someone actually looks directly at the NPC.

modify guy long This is just some random guy
Indenting file...
"/tmp/indent.1134436904.tmp.dat" 19 lines 408 bytes
Exit from ed.

Adjectives are useful for complementing NPCs and other objects. For example, if our guy is 'oily' or 'hairy' as described in his long description, a player would be able to do a look oily guy and see the guy even if "oily" isn't in his actual name/id.

modify guy adj
This setting takes multiple values. If you have no more values to
enter, then enter a dot on a blank line. To cancel, enter a single q on a blank
line.
You may now enter the next value. So far, it is blank.
If you're done entering values, enter a dot on a blank line.
hairy You may now enter the next value. So far, we have: ({ "just some" }) If you're done entering values, enter a dot on a blank line. stinky You may now enter the next value. So far, we have: ({ "just some", "random" }) If you're done entering values, enter a dot on a blank line. oily You may now enter the next value. So far, we have: ({ "just some", "random", "some" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "just some", "random", "some" }) Indenting file... "/tmp/indent.1134436924.tmp.dat" 19 lines 402 bytes Exit from ed. /realms/testycre/tmp/guy1134436912: Ok /realms/testycre/area/npc/guy: Ok SetAdjectives modification complete.

Let's look at our room and see if the Dude is appearing as expected.

look
/realms/testycre/area/room/test2
Room 2 [w]
This is the second test room.
The Dude is standing here.

We'll check out the Dude's file and see how QCS has set up the NPC for us.

about dude
/realms/testycre/area/npc/guy.c

#include <lib.h>

inherit LIB_SENTIENT;

static void create() {
sentient::create();
SetKeyName("guy");
SetAdjectives( ({"just some", "random", "some"}) );
SetId( ({"dude", "fellow", "fella"}) );
SetShort("The Dude");
SetLong("This is just some random guy.");
SetLevel(1);
SetRace("human");
SetClass("explorer");
SetGender("male");
}

void init(){
::init();

Weapon Creation (Back to Top)

Now we'll create a weapon for our NPC. "hammer" is the filename.

create weapon hammer
I'm going to go with the appropriate area directory:
/realms/testycre/area/weap/hammer.c
You wave your hand mysteriously and a generic weapon materializes!

And then set the hammer's ID(s)

modify weapon id hammer
This setting takes multiple values. If you have no more values to
enter, then enter a dot on a blank line. To cancel, enter a single q on a blank
line.
You may now enter the next value. So far, we have: ({ "hammer" })
If you're done entering values, enter a dot on a blank line.
warhammer You may now enter the next value. So far, we have: ({ "hammer", "warhammer" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "hammer", "warhammer" }) Indenting file... "/tmp/indent.1134437181.tmp.dat" 19 lines 453 bytes Exit from ed. /realms/testycre/tmp/hammer1134437165: Ok /realms/testycre/area/weap/hammer: Ok SetId modification complete.

And now we will set the weapon's name to "hammer".

modify weapon name hammer
There is no weapon here.
look /realms/testycre/area/room/test2 Room 2 [w] This is the second test room. A generic weapon is here. The Dude is standing here.

What's happened here is that we changed the weapon's ID before the name. Luckily, this is easy to fix.

modify hammer name hammer
Indenting file...
"/tmp/indent.1134437205.tmp.dat" 22 lines 474 bytes
Exit from ed.

Now we'll look at the hammer's file to see how it looks.

about hammer
/realms/testycre/area/weap/hammer.c

#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
item::create();
SetKeyName("hammer");
SetId( ({"hammer", "warhammer"}) );
SetAdjectives( ({ "generic" }));
SetShort("a generic weapon");
SetLong("A weapon of indeterminate proportions.");
SetMass(50);
SetVendorType(VT_WEAPON);
SetClass(30);
SetDamageType(BLADE);
SetWeaponType("blade");

}
void init(){
::init();
}

We can now set the hammer's damage type to blunt for a nice crushing effect.

modify hammer damagetype blunt
Indenting file...
"/tmp/indent.1134437392.tmp.dat" 22 lines 474 bytes
Exit from ed.

And now set the weapon type.

modify hammer weapontype blunt
Indenting file...
"/tmp/indent.1134437398.tmp.dat" 22 lines 474 bytes
Exit from ed.

Similarly, set the mass.

modify hammer mass 700
Indenting file...
"/tmp/indent.1134437414.tmp.dat" 22 lines 475 bytes
Exit from ed.

We will now make the weapon require two hands to use.

modify hammer hands 2
Indenting file...
"/tmp/indent.1134437422.tmp.dat" 23 lines 492 bytes
Exit from ed.

We'll double-check our hammer's file now to see if everything was set.

about hammer
/realms/testycre/area/weap/hammer.c

#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
item::create();
SetKeyName("hammer");
SetId( ({"hammer", "warhammer"}) );
SetAdjectives( ({ "generic" }));
SetShort("a generic weapon");
SetLong("A weapon of indeterminate proportions.");
SetHands(2);
SetMass(700);
SetVendorType(VT_WEAPON);
SetClass(30);
SetDamageType(BLUNT);

SetWeaponType("blunt");
}

void init(){
::init();
}

Now we'll set that short description.

modify hammer short a heavy war hammer
Indenting file...
"/tmp/indent.1134437450.tmp.dat" 23 lines 494 bytes
Exit from ed.

And our long description...

modify hammer long This is an extremely large and heavy hammer designed to be wielded in both hands and used to hurt people very badly indeed.
Indenting file...
"/tmp/indent.1134437509.tmp.dat" 23 lines 579 bytes
Exit from ed.

Setting some adjectives.

modify hammer adj
This setting takes multiple values. If you have no more values to
enter, then enter a dot on a blank line. To cancel, enter a single q on a blank
line.
You may now enter the next value. So far, it is blank.
If you're done entering values, enter a dot on a blank line.
large You may now enter the next value. So far, we have: ({ "large" }) If you're done entering values, enter a dot on a blank line. heavy You may now enter the next value. So far, we have: ({ "large", "heavy" }) If you're done entering values, enter a dot on a blank line. war You may now enter the next value. So far, we have: ({ "large", "heavy", "war" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "large", "heavy", "war" }) Indenting file... "/tmp/indent.1134437531.tmp.dat" 23 lines 592 bytes Exit from ed. /realms/testycre/tmp/hammer1134437521: Ok /realms/testycre/area/weap/hammer: Ok SetAdjectives modification complete.

And finally, look at our hammer file.

about hammer
/realms/testycre/area/weap/hammer.c

#include <lib.h>
#include <damage_types.h>
#include <vendor_types.h>

inherit LIB_ITEM;

static void create() {
item::create();
SetKeyName("hammer");
SetAdjectives( ({"large", "heavy", "war"}) );
SetId( ({"hammer", "warhammer"}) );
SetShort("a heavy war hammer");
SetLong("This is an extremely large and heavy hammer designed to be wielded
in both hands and used to hurt people very badly indeed.");
SetHands(2);
SetMass(700);
SetVendorType(VT_WEAPON);
SetClass(30);
SetDamageType(BLUNT);

SetWeaponType("blunt");
}

void init(){
::init();
}

It's a pretty heavy hammer, so let's make sure our guy can wield it.

modify guy level 10
Indenting file...
"/tmp/indent.1134437557.tmp.dat" 19 lines 403 bytes
Exit from ed.

With this simple command we add the hammer to the permanent inventory of our guy.

add hammer to guy
ob2: /realms/testycre/area/npc/guy.c
ob: /realms/testycre/area/weap/hammer.c
Please enter a command for the NPC to perform with this item. If you
have no such command to enter, enter the number of these items you want to add:
wield hammer Indenting file... "/tmp/indent.1134437569.tmp.dat" 22 lines 489 bytes Exit from ed. /realms/testycre/area/npc/guy: Ok Guy wields a heavy war hammer. SetInventory modification complete.

And now we take a look at our guy.

exa guy
This is just some random guy.
The male human is in top condition.
Guy is carrying:
A heavy war hammer (wielded in left hand and right hand)

And check the guy's file.

about guy
/realms/testycre/area/npc/guy.c

#include <lib.h>

inherit LIB_SENTIENT;

static void create() {
sentient::create();
SetKeyName("guy");
SetAdjectives( ({"just some", "random", "some"}) );
SetId( ({"dude", "fellow", "fella"}) );
SetShort("The Dude");
SetLong("This is just some random guy.");
SetInventory(([
"/realms/testycre/area/weap/hammer" : "wield hammer",
]));
SetLevel(10);
SetRace("human");
SetClass("explorer");
SetGender("male");
}

void init(){
::init();
}

Armor Creation (Back to Top)

Making armor is just as easy.

create armor helmet
I'm going to go with the appropriate area directory:
/realms/testycre/area/armor/helmet.c
You wave your hand mysteriously and generic armor materializes!
modify armor name helmet Indenting file... "/tmp/indent.1134437645.tmp.dat" 18 lines 483 bytes Exit from ed. modify helmet id This setting takes multiple values. If you have no more values to enter, then enter a dot on a blank line. To cancel, enter a single q on a blank line. You may now enter the next value. So far, it is blank. If you're done entering values, enter a dot on a blank line. helm You may now enter the next value. So far, we have: ({ "helm" }) If you're done entering values, enter a dot on a blank line. headgear You may now enter the next value. So far, we have: ({ "helm", "headgear" }) If you're done entering values, enter a dot on a blank line. cover You may now enter the next value. So far, we have: ({ "helm", "headgear", "cover" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "helm", "headgear", "cover" }) Indenting file... "/tmp/indent.1134437661.tmp.dat" 22 lines 535 bytes Exit from ed. /realms/testycre/tmp/helmet1134437649: Ok /realms/testycre/area/armor/helmet: Ok SetId modification complete. modify helmet short a horned viking helmet Indenting file... "/tmp/indent.1134437692.tmp.dat" 22 lines 544 bytes Exit from ed. modify helmet long Vikings
didn't really wear horned helmets into combat, but this one does look
formidable with its large bull horns and thick iron construction. It
should prove very protective.
Indenting file... "/tmp/indent.1134437772.tmp.dat" 22 lines 666 bytes Exit from ed.
modify helmet adj This setting takes multiple values. If you have no more values to enter, then enter a dot on a blank line. To cancel, enter a single q on a blank line. You may now enter the next value. So far, it is blank. If you're done entering values, enter a dot on a blank line. iron You may now enter the next value. So far, we have: ({ "iron" }) If you're done entering values, enter a dot on a blank line. thick You may now enter the next value. So far, we have: ({ "iron", "thick" }) If you're done entering values, enter a dot on a blank line. viking You may now enter the next value. So far, we have: ({ "iron", "thick", "viking" }) If you're done entering values, enter a dot on a blank line. horned You may now enter the next value. So far, we have: ({ "iron", "thick", "viking", "horned" }) If you're done entering values, enter a dot on a blank line. formidable You may now enter the next value. So far, we have: ({ "iron", "thick", "viking", "horned", "formidable" }) If you're done entering values, enter a dot on a blank line. protective You may now enter the next value. So far, we have: ({ "iron", "thick", "viking", "horned", "formidable", "protective" }) If you're done entering values, enter a dot on a blank line. . Entries complete. Final array is: ({ "iron", "thick", "viking", "horned", "formidable", "protective" }) Indenting file... "/tmp/indent.1134437802.tmp.dat" 22 lines 722 bytes Exit from ed. /realms/testycre/tmp/helmet1134437782: Ok /realms/testycre/area/armor/helmet: Ok SetAdjectives modification complete. about helmet /realms/testycre/area/armor/helmet.c #include <lib.h> #include <armor_types.h> #include <damage_types.h> inherit LIB_ARMOR; static void create(){ armor::create(); SetKeyName("helmet"); SetAdjectives( ({"iron", "thick", "viking", "horned", "formidable", "protective"}) ); SetId( ({"helm", "headgear", "cover"}) ); SetShort("a horned viking helmet"); SetLong("Vikings didn't really wear horned helmets into combat, but this one does look formidable with its large bull horns and thick iron construction. It should prove very protective."); SetMass(50); SetDamagePoints(100); SetArmorType(A_BODY_ARMOR); SetProtection(BLUNT, 20); SetProtection(BLADE, 20); SetProtection(KNIFE, 20); } void init(){ ::init(); } modify helmet armortype helmet Indenting file... "/tmp/indent.1134437818.tmp.dat" 22 lines 718 bytes Exit from ed. modify helmet mass 200 Indenting file... "/tmp/indent.1134437830.tmp.dat" 22 lines 719 bytes Exit from ed. modify helmet protection Your armor can protect against one or more of the following types of damage: blunt, blade, knife, water, shock, cold, heat, gas, acid, magic, poison, disease, trauma, .. Please enter which ones your armor should protect from, one at a time. When you are done, please type a dot on a blank line. blunt You may now enter the next value. So far, we have: ({ "blunt" }) If you're done entering values, enter a dot on a blank line. blade You may now enter the next value. So far, we have: ({ "blunt", "blade" }) If you're done entering values, enter a dot on a blank line. knife You may now enter the next value. So far, we have: ({ "blunt", "blade", "knife" }) If you're done entering values, enter a dot on a blank line. trauma You may now enter the next value. So far, we have: ({ "blunt", "blade", "knife", "trauma" }) If you're done entering values, enter a dot on a blank line. . Protections list complete. Please enter the protection value for: BLUNT 15 Please enter the protection value for: BLADE 20 Please enter the protection value for: KNIFE 25 Please enter the protection value for: TRAUMA 10 This is where the mapping gets sent somewhere. ProtectionsMap is: ([ "BLADE" : 20, "BLUNT" : 15, "TRAUMA" : 10, "KNIFE" : 25 ]) Indenting file... "/tmp/indent.1134437901.tmp.dat" 23 lines 750 bytes Exit from ed. about helmet /realms/testycre/area/armor/helmet.c #include <lib.h> #include <armor_types.h> #include <damage_types.h> inherit LIB_ARMOR; static void create(){ armor::create(); SetKeyName("helmet"); SetAdjectives( ({"iron", "thick", "viking", "horned", "formidable", "protective"}) ); SetId( ({"helm", "headgear", "cover"}) ); SetShort("a horned viking helmet"); SetLong("Vikings didn't really wear horned helmets into combat, but this one does look formidable with its large bull horns and thick iron construction. It should prove very protective."); SetMass(200); SetDamagePoints(100); SetArmorType(A_HELMET); SetProtection(BLADE, 20); SetProtection(BLUNT, 15); SetProtection(TRAUMA, 10); SetProtection(KNIFE, 25); } void init(){ ::init(); } l /realms/testycre/area/room/test2 Room 2 [w] This is the second test room. A horned viking helmet and a heavy war hammer are here. The Dude is standing here. exa dude This is just some random guy. The male human is in top condition. Guy is carrying: A heavy war hammer (wielded in left hand and right hand) add helmet to dude ob2: /realms/testycre/area/npc/guy.c ob: /realms/testycre/area/armor/helmet.c Please enter a command for the NPC to perform with this item. If you have no such command to enter, enter the number of these items you want to add: wear helmet Indenting file... "/tmp/indent.1134437927.tmp.dat" 23 lines 544 bytes Exit from ed. /realms/testycre/area/npc/guy: Ok Guy wields a heavy war hammer. Guy wears a horned viking helmet. SetInventory modification complete. exa dude This is just some random guy. The male human is in top condition. Guy is carrying: A heavy war hammer (wielded in left hand and right hand) A horned viking helmet (worn)

Adding Room Resets (Back to Top)

Ok our dude is done. Let's clean up the room by updating it.

update
Updating environment
/realms/testycre/area/room/test2: Ok
look /realms/testycre/area/room/test2 Room 2 [w] This is the second test room. pwd /realms/testycre: cd area/npc /realms/testycre/area/npc:

We need to have the guy present in order to add him to the room:

clone guy
Guy wields a heavy war hammer.
Guy wears a horned viking helmet.
You clone The Dude (/realms/testycre/area/npc/guy.c).
add guy to room ob2: /realms/testycre/area/room/test2.c ob: /realms/testycre/area/npc/guy.c Please enter the number of these that you want to add: 1
Indenting file... "/tmp/indent.1134437999.tmp.dat" 26 lines 485 bytes Exit from ed. /realms/testycre/area/room/test2: Ok /realms/testycre/area/room/test2 Room 2 [w] This is the second test room. The Dude is standing here. SetInventory modification complete. update Updating environment /realms/testycre/area/room/test2: Ok

That's it. Easy, huh? Think of how much slogging through ed this would save you when making a large area.

look
/realms/testycre/area/room/test2
Room 2 [w]
This is the second test room.
The Dude is standing here.

exa dude This is just some random guy. The male human is in top condition. Guy is carrying: A heavy war hammer (wielded in left hand and right hand) A horned viking helmet (worn) more here #include <lib.h> #include "/realms/testycre/customdefs.h" inherit LIB_ROOM; static void create() { room::create(); SetClimate("indoors"); SetAmbientLight(30); SetShort("Room 2"); SetLong("This is the second test room."); SetExits(([ "west" : "/realms/testycre/area/room/test1", ])); SetItems( ([ "template" : "That's what this is.", ]) ); SetInventory(([ "/realms/testycre/area/npc/guy" : 1, ])); } void init(){ ::init(); } quit Please come back another time!

The End (Back to Top)

Obviously you still need to code some LPC in ed for complex stuff. But knocking out rooms and NPC's and objects quickly helps you avoid getting bogged down in mechanics when what you really want to do is build.

Return to Dead Souls Homepage