Scallywag Scripting Guide
Author: Scott Wakeling
Last Revised, August 18th 2007
Requirements: Scallywag: Lair of the Medusa *full version
1.0 Scallywag Quick Start
1.1 How to Install MODs
If you already know how to download and install mods, you can skip to the next section.
If you haven't already downloaded your first mod and tried running it from the main menu of Scallywag, now is the time to do it. Zombie Fest is the standard demo mod. You can find it on the MODS page of Chronic's website, at www.chronicreality.co.uk
When you start experimenting with what Scallywag can do, you want somewhere safe to do it. While all the Scallywag game scripts and resources (textures, sounds etc.) are right there to be seen and played with in the game's installation folder, in /Media, modifying them will alter how the core Scallywag game plays. You need a basic mod to play with while you learn. I suggest you use Zombie Fest.
Unzip the “Zombie Fest” mod into the /Mods folder of your Scallywag installation directory. You'll have a \Scallywag\game\Mods\Zombie Fest folder now, inside of which you'll see folders for Config, Libs, Fonts etc.
Now, run Scallywag, hit the MODS button on the main menu, choose Zombie Fest from the drop-down list, and click LOAD. The main title screen will show a grisly scene of zombies lurching out the darkness, and if you click PLAY GAME (or LOAD, or OPTIONS for that matter), you'll be working with the mod, not the original Scallywag game. Any changes to the Options, or saved games, are all made inside the Zombie Fest directory. Next time you run the game, Scallywag will launch by default, and you can choose another mod to play from there, or just play Scallywag instead.
You can also tell Scallywag to run your chosen mod by default on startup. To do this, pass your mod's name on the command line to scallywag.exe (e.g. create a shortcut to scallywag.exe, edit the shortcut properties, change the target to, for example, "C:\Program Files\Scallywag\game\scallywag.exe" Zombie Fest
1.2 What is a MOD?
All the settings for a mod's equipment, items, monsters, and levels are in the .cfg files (just regular text files) in the mod's /Config directory. Any textures, sounds or fonts referenced by these script files are similarly placed in the /Textures, /Sounds and /Fonts folder as appropriate. As an experiment, try copying the contents of Scallywag's /Media folder to a new folder named MyMod, in the /Scallywag/game/Mods folder.*
You'll now have the following:
Run Scallywag, load MyMod, and behold, you appear to be playing Scallywag, but it's really MyMod. Your first mod is complete. Easy huh?
Everything that defines a game, is inside its root folder. Loading a mod redirects the engine from looking at the default /game/Media directory, to look at your mod's folder instead. Change anything inside your mod folder, and your change will be reflected in the game.
*Did you do it? Well go on and do it then! Don't make me beast you!
1.3 What's in a MOD?
Scallywag uses a data-driven engine. It sucks in scripts, textures and sounds from a folder you specify, and generates a random adventure game (RAG) with it. This is what happens when you load a mod. You point the engine to the mod's folder, it sucks in all the data, and makes a random game with it. Job done! Just like that! What the engine does with its time off I don't know, I'll ask it next time I get a day off myself.
All the data inside a mod's root folder defines the game you play when that mod is running. If you create new monsters and you have new images to represent them in-game, put the images in your mod's /Textures folder.
Let's see what each folder is for:
/Config contains all the game's attribute scripts. These define how strong monsters are, how rare a certain magic item is, what things look like, etc. Config files are just regular text files, so you can edit them in whatever you like, Notepad, Wordpad, Open Office.. The .cfg files the game actually uses are listed in the RAG.Configs attribute in main.cfg. If you add some new scripts for your mod, don't forget to add them to this list.
/Fonts contains the fonts used by the engine. Creating and using new fonts is an advanced topic, we'll deal with it another day.
/Libs contains plug-ins that add entirely new functionality to the engine. You have to be a C++ programmer to write plug-ins, so we'll deal with Libs another day. If you're not a programmer, you'll still be able to drop new plug-ins in here, written by other people, and start making use of the new types they've made available to you, so it's all good!
/Maps doesn't need to exist, but if you press Ctrl+Print Screen during play, a little image file will appear in here of the level you were playing.
/Saves is where save games get saved out to.
/Sounds is where all the game's sounds are stored as .wav files
/Textures is where all the game's textures get saved; monster graphics, wall textures, menu buttons etc.
Equipment, Items, and Monsters
2.1 Weapons and Armour
Now you know all about mods, we can get started with making one. Work in the MyMod folder, or Zombie Fest, or create a new mod with the bare essentials like menu textures and fonts and everything in place. From now on, I'm going to assume you're working inside a mod folder, and not altering Scallywag's core game files.
Open up weapons.cfg and look at the top of the file. You will see:
This defines three basic types, we have a Weapon, a WeaponPickup, and a RangedWeapon. Each type has its name inside square brackets, followed by a list of attributes. All scripted types have to be a type of something native, from inside the engine (or a plug-in from the /Libs folder). Native types are typically prefixed CtRAG, to mark them as a RAG engine class. All the basic native types and their attributes are comprehensively listed at the end of this document.
Weapon is said to be a type of CtRAGWeapon, or, it said to derive or inherit from CtRAGWeapon. It takes on all the basic settings and functionality of CtRAGWeapon, and then defines some of its own attributes. All the melee weapons you see in the game, like the Dagger, and the Spear, and all the others, all derive from Weapon, so you can see that scripted types can derive from other scripted types. They just need to wind up with an engine class somewhere at the bottom. So Dagger derives from Weapon, and Weapon derives from CtRAGWeapon. Let's look at the script for Dagger:
We can see the Dagger is a type of Weapon, so it gets all of Weapon's attributes, plus all the settings and functionality that Weapon gets from CtRAGWeapon. The Dagger does 4 damage when it hits something, the game describes it as a “Steel Dagger” when you mouse over it in your inventory, it needs one hand to equip, it has an image specified for how it should appear in the inventory (i.e. on the player's HUD), and it has a Speed of 1.1, which means 1.1 attacks per second (faster than the Axe, at 0.9).
We can use Dagger, or any other weapon, as a base type for something new and slightly different. Try adding the following script below Dagger (Dagger has to come first, so BigDagger knows about it):
Text=Big Steel Dagger
We just need to specify the attributes we are changing. HUDIcon and EquipsOn are inherited from the Dagger type, but because BigDagger doesn't set them to something else, they remain as they are. If we wanted to change the weapon's icon, or what anatomy parts were needed to use it, we could override those attributes too.
You'll notice Weapon has NoAutoSpawn set to 1, which means true. Objects with the NoAutoSpawn flag set do not automatically spawn, or get created, when a new map is generated. This is standard, there are so many scripted types of objects referenced from various places, but not all of them are visible in the game world. For an example, look in Scallywag's hints.cfg To try out our new BigDagger weapon, we just need to create a new pickup type for it. Try this (remember, anywhere after PickupDagger):
As you can see, the pickup for our new BigDagger weapon derives from the normal DaggerPickup, but we've made the pickup bigger, we've changed its Tooltip, and we've altered its Rarity and Levels attributes. Notice how we inherit NoAutoSpawn=0 from PickupDagger. This means our pickup will physically generate in the game world.
Levels states the minimum and maximum levels you can find this item on, Rarity has been set to 0.0 which is a special value that means one single instance of the item will always appear on those levels. If an item's Rarity is not zero, it is at the mercy of the random map generator. Rarity 0.1 is much rarer than 0.5 for example, but not even that means the 0.5 item will always generate. Only Rarity 0.0 guarantees the item generates. For this reason, things like the level exit, the rope, and the key in Scallywag, use a Rarity of 0.0, because the game revolves around needing one of each on every level.
PickupBigDagger knows what kind of item to give the players when it's collected, because of its name. The item name is on the end. Make sure it's the same as your item name, or the pickup will not give you anything!
If you run your MOD now, you'll find a Big Dagger on level 1. Try it. Try creating some more weapons, and experimenting with the Rarity and Levels attributes.
As a final exercise, try deriving from Catapult to make a BlowPipe. You'll need to make a PickupBlowPipe type so you can get hold of your new weapon, and you'll need to change the AmmoType variable to a new type, Dart – unless you want your BlowPipe to shoot Rocks! For extra credit, take a look at armour, it's much the same as basic weaponry but with different attributes.
There are many more attributes to experiment with, just for weapons alone! Try looking through the existing scripts to learn more, or check out some more tutorials. Here are the important ones:
EquipEffects – Can make you fly, immune to fire, invisible etc. This attribute takes a list of mutators, which will be covered at a later date. Suffice to say, mutators are the quickest and easiest way for users writing plug-ins to grant the community useful new effects.
EquipsOn – Anatomy parts (see below) needed for an entity to equip this item. For example, a two-handed weapons needs two hands, a ring needs a finger. IcarusWings need a Back. Anatomy and EquipsOn control what body slots get used by different types of equipment, and who can equip what. This is really useful if you're planning to mod together some new character classes that have restrictions on what equipment they can use.
Edge – Lists damage types to be applied when this weapon does damage, or material names to specify what some armour is made form. Examples include a flaming sword doing Fire damage, which can be hooked into a creature via Special=ProneTo(Fire) (see below), and armour being given the Metal edge, to make it susceptible to the Rust Monster's ooze attack.
2.2 Items and Compounds
When we refer to items in Scallywag, we're really talking about things like food, oil, chest keys, and the rope. If you look at the scripts for these items, you'll see they all derive from CtRAGItem, which exposes the following attributes:
UseEffects – Mutators (special effects) to apply to the user of this item (more on mutators later)
Charges – Used by charged items like wands
UseSound – Sound effect to play when used
StackSize – How many of these can fit in one inventory slot
CompoundOf – Type these items can be combined into
CompoundSize – The number of items of this type you need to make an item of type CompoundOf
Weapons and armour also inadvertently derive from CtRAGItem via CtRAGEquipment (you can learn what types derive from what by looking them up at the end of this document), so weapons and armour can be charged, play sound effects when they are used, have charges, and be combined into other types (try collecting five whips in Scallywag as an example, and look up its script).
Some items exist only to be used to activate a widget of some kind (rope and staircase, key and chest). They cant be used by being clicked on because they don't have any UseEffects listed and have Charges set to -1, which means they don't get used in that way.
To create new items that can be made into other more useful items, use the Compound attributes, and as always, look in the Scallywag scripts for examples. You'll find wands are scripted to have charges, and all the Food items in the game are types of CtRAGItem, so they default to Charges=1, but there's no reason you should feel limited to that. Charged items don't stack because there is no way to tell which one is being used when the user clicks on the slot they are in.
All monsters are types of Enemy. Creating new monsters is as simple as choosing one that's a close match to what you want, and overriding the attributes you want to change. For the adventurous among you, the following attributes are available:
Size, Width, Height – Set only Size if you are happy with your monster being square, or use Width and Height to get things just right.
Strength, Health – Strength is a creature's base melee damage before weapon strength is applied. Health is self explanatory.
LeavesCorpse – If set to 1, when the creature dies, a corpse of type DeadX will be created, where X is the name of your monster. Look at Rat, DeadRat and PickupDeadRat for an example.
Anatomy – Lists the body parts the creature has (controls what equipment may be used)
CanCarry – Defines what item types this creature might be given when the map is generated (check the scripts for the bosses in Scallywag, they all have CanCarry=Rope
ToHit – A chance out of 20 that the creature can hit in combat (melee or ranged), before being modified by the targets Defence attribute.
XP – Gained by the killer if this beastie dies.
IQ – Mainly reserved for plug-ins to create more intelligent behaviours, but already used minimally by Scallywag. If IQ is 2 or higher, a creature will seek to use healing items and foods when it reacheas 50% Health.
StartEquip – What the creature always gets as a start, before map generation may or may not grant them anything else. Use this if you always want your Balrog to have a Whip.
Special – Feats and skills. This lists all a creature's default mutators. This is all covered later, but this is where you list things like being able to fly, or being immune to a certain type of damage, or anything else that might be provided at a later date by plug-ins.
Touch – If a monster has a special touch attack, its type is specified here. For example, a spider bite is poisonous and so needs to be scripted as a separate type, to be given its HitEffects. Giving the Spider suitable anatomy for equipping such a weapon, and not scripting a Pickup type for it so it may not be dropped when the Spider is killed would also work, but I thought specifying a Touch weapon was tidier.
HUDColour – This attribute comes from CtRAGActor, which Enemy derives from. I note it here so you know if you script a new player type (rogue, wizard, etc.) you know you can change the HUDColour. It takes 4 numbers, for ARGB (A is for alpha, make it 255 for solid). So for a bright colour, that just uses the colours in the textures, use 255,255,255,255, but for a red tinge, use 255,255,200,200 (drop the green and blue channels to make the colour show red).
3.0 Map Generation and Level Info
Maps are randomly generated in Scallywag, and will be in any MOD you make (unless you write a plug-in map type that loads from a file instead of being random generated). You can control the textures on the floors and walls, the map density, the wall height, overall map size, and to a limited degree, the types of rooms the map can contain.
Control how your map generates for a given level by scripting LevelInfo objects. See Levels.cfg in Scallywag for examples, and check out the following attributes:
RoomCount – The standard Scallywag map type cnsists of tunnels, and rooms, caverns or both. If you want square rooms in your map, use this attribute as a hint. Map generation is not an explicit thing, other attributes like Density can result you not getting the exact room or cavern count you asked for. To make your maps bigger, make this attribute higher.
CavernCount – As RoomCount, but for caverns (diamond shaped areas).
Music – Background music, if any, for this level(s)
WallHeight – As a ratio to floor tile size (so set it to 1 to have walls as high as single width tunnels are wide, and set it to 2 for twice as high, or something else, like 1.666).
Density – A number between 0 and 100. Used as a hint to the map generator. The lower the number, the more spaced out your map will be (i.e. the longer your tunnels are going to be).
Complete – Set it to 1 if the game is completed when the player arrives on this level (see Scallywag's level 81 for an example).
Desc – Describes the level/range of levels. E.g. “Dirt Caves”.
LevelHint – Text for a hint scroll if you want to show the player a hint on reaching this level, could also be used to show objectives or story.
TunnelFloor, RoomFloor, CavernFloor, TunnelWall, RoomWall, CavernWall – Specify the map's textures here.
ExitFloor – Texture for the exit hole, if you are using the exit as Widget.IsFloor=1 method.
Special – Environmental effects, taken as a list of mutators. Mutators are dealt with later.
Try experimenting with how different you can get your maps looking, and feeling. There are so many different combinations of map size, density and wall height, that coupled with music and different textures, there's great variation to be found even without native plug-ins. As new map generator plug-ins appear, be sure to check them out and see what new options they are making available.
Mutators are all the special abilities and effects you see in the game. They can be applied to actors (the player, monsters etc.), items, or even entire maps. They make it easy to share around some functionality, so instead of creating flying monsters, you create flying as a mutator, and attach to whatever it makes sense to have it (so, flying invisible Pickups are easily made, as are talking doors, once somebody writes a conversation plug-in).
This article describes the mutators that are available to users of vanilla Scallywag. I expect mutators to be the single biggest source of new functionality via plug-ins for the future, so be sure to keep up to date with what's available.
Here's what you can use as standard, in any combination:
Armour – Takes a single parameter, the amount by which to boost the mutated actor's Defence attribute. E.g. Give a suit of armour or a ring EquipEffects=Armour(4)
Drain – When applied, has a 1/10 chance of draining the victim of one rank (reducing Health, ToHit etc. in the process). E.g. Give a weapon or touch attack HitEffects=Drain. Removes straight after application.
Drunk – Takes a single parameter, units of alcohol that caused the stupor. This mutator is typically applied by using items of native type Alcohol (see GobboAle), but you could use it for other things I'm sure.
Flying – When applied, causes an actor to fly. Permanent until removed by the Remove mutator, or until the actor tries to pick something up from the ground. E.g. Give a potion of flight UseEffects=Flying
Heal – Takes a single parameter, the number of Health points to restore. Removes straight after application.
Heat – Applies time-based damage with edge types Heat, and Internal. Applied as an environmental effect by the Magma Cavern levels in Scallywag. Script some item that offers ImmuneTo(Heat) to protect from this effect. Single parameter is damage per second.
Hungover – Applied by the Drunk mutator when it is removed. Takes a single parameter that specifies how long the hangover should last (depends how drunk the actor was initially).
Hypothermia – As Heat, but applied time-based damage with edge types Cold and Internal. Single parameter is damage per second.
Immune – Single parameter is a mutator name or edge type. If a mutator is specified, mutators of that type may not be applied to this actor (E.g. Immune(Drain)), if it is an edge type, the actor is immune to any damage that comes in with that edge type (E.g. Immune(Cold)). As with all mutators, list as many as you like. E.g. Special=Flying,Immune(Cold),Immune(Drain),Prone(Smashing)
Invisible – Makes an actor invisible until it attacks something.
Lycanthropy – A time-based disease that when manifests, grants the mutated actor immense strength, but causes them to take terrible damage at the same time. Cured by eating the Belladonna herb, which is scripted to have UseEffects=Remove(MUTLycanthropy) (note the Remove mutator needs mutator names prefixed with MUT, see below).
Melt – Ruins any equipped items in the mutated actor's inventory that have an Edge type specifed by Melt's single parameter. E.g. HitEffect=Melt(Chocolate) would ruin any chocolate weapons an actor has currently equipped. Removes straight after application.
Petrified – Slows an actor down, removes Flying, and inflicts terrible damage.
Poison – Lasts 60 seconds, takes a single parameter, damage per second. Damage inflicted by this mutator has the Internal edge, so armour does not protect you. When naming mutators like this from other mutators, use * to mean, all instances of, no matter the varying parameters. For example, to remove all active poisons (of possibly varying strengths), use UseEffects=Remove(MUTPoison*). To just remove a known type of insect poison, use UseEffects=Remove(MUTPoison(0.1)), if you know that poison's strength was 0.1
Prone – Lists edge types this actor takes double damage from. E.g. Special=Prone(Smashing)
Random – Takes a list of mutators and applies one at random. E.g. UseEffects=Random(Speed,Speed,Slow), gives a choice of three, with Slow being a little rarer than Speed. You can also list mutators that take parameters. Imagine a sword that has Edge=Smashing doing HitEffects=Random(Drain,Prone(Smashing)). Evil or what? For each instance of Prone running on an actor, damage it is prone to is doubled, so this sword gets more powerful every time it hits something!
Regenerate – Takes a single parameter, points of Health to restore per second. This mutator is removed if its owner takes damage with edge type Fire.
Remove – Takes a mutator name to remove. Does some special pattern matching to find the mutators you want removed. Use a * in place of parameters, if the mutator you are trying to remove normally takes a parameter (e.g. Poison). Or specify the parameter if you know it. Always prefix mutator names to remove with MUT, e.g. A weapon with HitEffects=Remove(MUTFlying) will drop fliers to the floor permanently. Removes straight after application.
RevealMap – Reveals all contents of the minimap. Removes straight after application. Some mutators are like this, they are great for creating new functionality and attaching it wherever is useful. For example, if a conversation plug-in is written as a mutator, anything could talk that you can put a mutator on, be it a monster, some other actor, or even a treasure chest, or door (when somebody writes a plug-in for that).
Slow – Takes a single parameter, amount to decrease Speed by.
Speed – Takes a single parameter, amount to increase Speed by.
Strength - Takes a single parameter, amount to increase the mutated actor's Strength by.
Weakness – Lets you specify the one and only Edge type this actor can be hurt by. E.g. Use Special=Weakness(Silver) for a creature that may only be hurt by silver weapons.