Crashcourse - Part 07

[previous part] [Table of contents] [next part]

It's time to really start annoying the players. And, maybe please them a bit too, along the way? Naaah.. ;-)

When dealing with players extra care has to be taken to prevent nasty accidents to happen. And to eliminate any loopholes they might try to take advantage of. We must be certain that the player is cleaned up after our functions finish. And no permanent changes must be done to the players.

There is another important aspect of these kind of items. They should under no circumstances give the players too big advantages. The items should be balanced so that they either give small advantages, or that they have some disadvantages. So, if an item give a player +2 in a stat, then it should have some other disadvantages. Disadvantages may be -stats, draining of hps/sps/money/exp, can only be worn by a certain alignment, lowering of armour class, etc.

You should read 'man Guidelines' before proceeding with this course...

FILENAME: hat.c

This file uses the easiest way of changing a player's stats, using the function add_modifier(). You can both increase and decrease the wearer's stats when he/she/it wears the hat by using either positive or negative values. Please refer to 'man add_modifier' for more info.

FILENAME: hat2.c
FILENAME: hat2funcs.c

This hat will increase the player's int with 2, but decrease the player's dex with 1. Since the player should only get advantages when the hat is worn, we hook the __wear and __remove operations on the hat. This will enable us to activate the advantage when the hat is worn and deactivate it when the hat is removed. This is the standard method of giving an armour special abilities. And if you take a look at the funcfile, you will see that the functions are written in such a way that implementing them later for another armour would be easy. As you can see only the last parts of the two functions would need to be changed (and the names of the functions, of course). These functions could of course be written in such a way that several items could use the same files, yes even the same functions, but I would not recommend this unless the items/functions are related in some way. The functionfiles can often get messy, and the more functions/items they're referring to, the worse it gets. Believe me, I know. I have read through quite a lot of functions, both some of my own and some during my work as a QC Arch that wasn't what I would call a textbook example of good and clean coding.

There are mainly four functions for messing around with playerstats:

add_tmp_str(int str)  - Add str to the player's strength.
add_tmp_dex(int dex)  - Add dex to the player's dexterity.
add_tmp_int(int int)  - Add int to the player's intelligence.
add_tmp_con(int con)  - Add con to the player's constitution.

If these functions receive a negative value, the stats will be decreased. These are all temporary changes to the player. Once the player quits the game, they will be gone.

FILENAME: gauntlets.c
FILENAME: gauntletsfuncs.c

These gauntlets gives the player two HUGE advantages: The player may not be diseased or disarmed. This will however only last for a short while after the gauntlets are worn. And the player is stung every time the gauntlets are worn. They are still too powerful, though. So if something like this should have gotten past QC they must have had some other major disadvantages. Perhaps you can think of something and code it? ;-) 'cause I've left it all up to you. It shouldn't be much of a problem to code for instance that the gauntlets vanish after three or four wears.

There's a new function called call_out() introduced here. This is a very useful function, because it allows us to call a function with a delay. The three parameters for it are: the name of the function to call, the time to delay the call in seconds and your own arguments, if any. The name of the function is not a functionpointer, it is just a string containing the name of the function without any paranthesis. This is because a call_out() can only call a function in the same object. There is one very important thing to note about call_out()s. These functions are DELAYED functioncalls, so you must be aware of the fact that a lot could have happened while the call_out() waited. Meaning that if you send an object through as an argument, you MUST check to see if the object is still there when the delayed function is called.

! AND YOU CANNOT USE 'this_player()' in a delayed function since this_player() would be set to 0 ! Rather send through the player object as an argument and use it instead(This is not really true anymore, but nonetheless stay away from this_player() in call_out()s!).

FILENAME: amulet.c

Making an object autoloading is pretty easy. All the object really need is a property called 'auto_load' in it. This property must contain the full path of the item plus the character ':'. It may also receive an argument after the colon, but this isn't neccessary.

There are however some important guidelines you should keep in mind when creating autoloading objects.

  1. It must not have any weight.
  2. It must prevent the player from dropping it.
  3. It must not be an actively usable item, like weapon or armour.
  4. It must not help the player in combats.

As you can see, we violated rule 3 in the amulet. But, this amulet is meant for wizards, and not active players. This is not a very strict rule, either, as auto-loading stuff can be an armour, but if so, it must provide no protection at all.
It may also be wise to include the property 'protected' to autoloading objects. This property will keep the item from being destroyed during combat.

FILENAME: soberdrink.c
FILENAME: soberfuncs.c

In this example, we have created a strange drink. Not only does it consume your money, but also your exp! Well, even if this example may be a bit weird, it can still be a good example. ;-)

The functions for messing around with the player's money and account is:

query_money()         - Will return how much money the player is carrying.
add_money(amount)     - Will increase (or decrease if negative) the amount
                        of money the player is carrying.
query_account()       - Will return the player's bank account.
set_accout(amount)    - Will set the player's account to a certain amount.
                        WARNING: This function will not change the
                        account, it will SET it.

There are two functions for changing and querying the player's exp:

query_exp()           - Will return the player's amount of experience points.
add_exp(exp)          - Will increase/decrease the player's amount of
                        experience points.

But, this drink does more than take away stuff from the player. It also makes the player sober and unsoaked. For the purpose of changing the player's eating/drinking status:
(All are indicated by a number, not "very drunk","incredible stuffed", etc.)

query_intoxication()    - Will return how drunk a player is.
add_intoxication(intox) - Will increase/decrease how drunk a player is.

query_soaked()          - Will return how soaked a player is.
add_soaked(soak)        - Will increase/decrease how soaked a player is.

query_stuffed()         - Will return how stuffed a player is.
add_stuffed(stuff)      - Will increase/decrease how stuffed a player is.

FILENAME: potion.c
FILENAME: potionfuncs.c

This potion will boost a player's strength and dexterity for a little while. If you read through the files, you will see nothing really new so I'm going to leave it all up to you. :-)
And it's not because I'm lazy. No, siree...

FILENAME: cape.c
FILENAME: capefuncs.c

This time we'll change the player's ability to sustain a certain type of damage. We have gone through the different damagetypes earlier and explained the different types of skills. In this example, we have used the skill called 'resist_cold', which will protect the player from cold.
You can read more about damagetypes and skills in the manualpage 'damage'. This cape could easily be rewritten using modifiers, and in this case, you wouldn't need a functionfile. How about you recoding it using modifiers? It's quite easy and much cleaner.

Hmmmm.. Looks like I've got less to say every course. Does this mean I'm lazy or that I expect you to have learned something? I hope the last one is right and that you actually have picked up something useful during these earlier courses. Well, we're not done yet, now are we? Next time we'll struggle for communication...


WRITTEN: 03 - Oct - 1996 - Gunner
LAST UPDATE: 27 - May - 1998 - Gunner
HTML Version: 03 - Feb - 2000 - Ghorwin

[previous part] [to the top] [Table of contents] [next part]