Crossfire Server, Branch 1.12  R12190
Functions | Variables
alchemy.c File Reference

This contains all alchemy-related functions. More...

#include <global.h>
#include <object.h>
#include <sproto.h>
#include <skills.h>
#include <spells.h>
Include dependency graph for alchemy.c:

Go to the source code of this file.

Functions

static void adjust_product (object *item, int lvl, int yield)
 We adjust the nrof of the final product, based on the item's default parameters, and the relevant caster skill level.
static void alchemy_failure_effect (object *op, object *cauldron, recipe *rp, int danger)
 Ouch.
static void attempt_do_alchemy (object *caster, object *cauldron)
 Main part of the ALCHEMY code.
static object * attempt_recipe (object *caster, object *cauldron, int ability, recipe *rp, int nbatches, int ignore_cauldron)
 Essentially a wrapper for make_item_from_recipe() and insert_ob_in_ob().
static int calc_alch_danger (object *caster, object *cauldron, recipe *rp)
 "Danger" level, will determine how bad the backfire could be if the user fails to concoct a recipe properly.
static const char * cauldron_sound (void)
 Returns a random selection from cauldron_effect[].
static int content_recipe_value (object *op)
 Recipe value of the entire contents of a container.
static recipefind_recipe (recipelist *fl, int formula, object *ingredients)
 Find a recipe from a recipe list that matches the given formula.
static object * find_transmution_ob (object *first_ingred, recipe *rp, size_t *rp_arch_index, int create_item)
 Looks through the ingredient list.
static int is_defined_recipe (const recipe *rp, const object *cauldron, object *caster)
 Determines if ingredients in a container match the proper ingredients for a recipe.
static object * make_item_from_recipe (object *cauldron, recipe *rp)
 Using a list of items and a recipe to make an artifact.
static int numb_ob_inside (object *op)
 Returns the total number of items in op, excluding ones in item's items.
static void remove_contents (object *first_ob, object *save_item)
 All but object "save_item" are elimentated from the container list.
int use_alchemy (object *op)
 Handle use_skill for alchemy-like items.

Variables

static const char *const cauldron_effect []
 define this for some helpful debuging information

Detailed Description

This contains all alchemy-related functions.

Definition in file alchemy.c.


Function Documentation

static void adjust_product ( object *  item,
int  lvl,
int  yield 
) [static]

We adjust the nrof of the final product, based on the item's default parameters, and the relevant caster skill level.

Parameters:
itemitem to adjust.
lvlalchemy skill level.
yieldhow many products the recipe returns at maximum.

Definition at line 373 of file alchemy.c.

References rndm().

Referenced by attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static void alchemy_failure_effect ( object *  op,
object *  cauldron,
recipe rp,
int  danger 
) [static]

Ouch.

We didnt get the formula we wanted. This fctn simulates the backfire effects--worse effects as the level increases. If SPELL_FAILURE_EFFECTS is defined some really evil things can happen to the would be alchemist. This table probably needs some adjustment for playbalance. -b.t.

Parameters:
opwho tried to do alchemy.
cauldroncontainer that was used.
rprecipe that failed.
dangerdanger value, the higher the more evil the effect.

Definition at line 502 of file alchemy.c.

References add_string(), recipestruct::arch_name, recipestruct::arch_names, attempt_recipe(), cast_magic_storm(), cauldron_sound(), change_attr_value(), CLEAR_FLAG, create_archetype(), draw_ext_info(), draw_ext_info_format(), fire_arch_from_position(), FLAG_CAN_ROLL, FLAG_CURSED, FLAG_IDENTIFIED, FLAG_KNOWN_CURSED, FLAG_NO_PICK, FOOD, free_object(), free_string(), generate_artifact(), get_formulalist(), get_random_mon(), get_random_recipe(), insert_ob_in_map(), insert_ob_in_ob(), llevDebug, LOG(), LOOSE_MANA, M_STONE, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_SUCCESS, NDI_UNIQUE, npc_call_help(), numb_ob_inside(), PREFER_HIGH, PREFER_LOW, QUERY_FLAG, random_roll(), remove_contents(), rndm(), SET_FLAG, SP_MED_FIREBALL, and summon_hostile_monsters().

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static void attempt_do_alchemy ( object *  caster,
object *  cauldron 
) [static]

Main part of the ALCHEMY code.

From this we call fctns that take a look at the contents of the 'cauldron' and, using these ingredients, we construct an integer formula value which is referenced (randomly) against a formula list (the formula list chosen is based on the # contents of the cauldron).

If we get a match between the recipe indicated in cauldron contents and a randomly chosen one, an item is created and experience awarded. Otherwise various failure effects are possible (getting worse and worse w/ # cauldron ingredients). Note that the 'item' to be made can be *anything *listed on the artifacts list in lib/artifacts which has a recipe listed in lib/formulae.

To those wondering why I am using the funky formula index method: 1) I want to match recipe to ingredients regardless of ordering. 2) I want a fast search for the 'right' recipe.

Note: it is just possible that a totally different combination of ingredients will result in a match with a given recipe. This is not a bug! There is no good reason (in my mind) why alchemical processes have to be unique -- such a 'feature' is one reason why players might want to experiment around. :) -b.t.

Parameters:
casterwho is doing alchemy.
cauldronthe cauldron in which alchemy should take place.

Definition at line 121 of file alchemy.c.

References alchemy_failure_effect(), recipestruct::arch_name, attempt_recipe(), calc_alch_danger(), recipestruct::cauldron, change_exp(), content_recipe_value(), recipestruct::diff, draw_ext_info(), draw_ext_info_format(), recipestruct::exp, F_IDENTIFIED, F_NOT_CURSED, F_TRUE, find_recipe(), find_skill_by_name(), FLAG_WIZ, get_formulalist(), recipestruct::index, is_defined_recipe(), llevDebug, LOG(), MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_MISSING, NDI_UNIQUE, numb_ob_inside(), recipeliststruct::number, PLAYER, PREFER_LOW, query_cost(), QUERY_FLAG, random_roll(), SK_EXP_NONE, recipestruct::skill, recipestruct::title, and recipeliststruct::total_chance.

Referenced by use_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static object * attempt_recipe ( object *  caster,
object *  cauldron,
int  ability,
recipe rp,
int  nbatches,
int  ignore_cauldron 
) [static]

Essentially a wrapper for make_item_from_recipe() and insert_ob_in_ob().

If the caster has some alchemy skill, then they might gain some exp from (successfull) fabrication of the product. If nbatches==-1, don't give exp for this creation (random generation/ failed recipe) If ignore_cauldron, don't check if we are using the matching cauldron type (shadow alchemy)

Parameters:
casterwho is trying to do alchemy.
cauldroncontainer used for alchemy.
ability?
rprecipe attempted.
nbatches?
ignore_cauldronif 0, checks the recipe uses the right cauldron type, else no check is done.
Returns:
generated item, can be NULL if contents were destroyed.
Todo:
check meaning of ability/nbatches.

Definition at line 305 of file alchemy.c.

References adjust_product(), recipestruct::cauldron, cauldron_sound(), draw_ext_info(), draw_ext_info_format(), find_skill_by_name(), FORCE, insert_ob_in_ob(), recipestruct::keycode, llevDebug, LOG(), make_item_from_recipe(), MSG_TYPE_SKILL, MSG_TYPE_SKILL_ERROR, MSG_TYPE_SKILL_FAILURE, MSG_TYPE_SKILL_SUCCESS, NDI_UNIQUE, remove_contents(), recipestruct::skill, recipestruct::title, and recipestruct::yield.

Referenced by alchemy_failure_effect(), and attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static int calc_alch_danger ( object *  caster,
object *  cauldron,
recipe rp 
) [static]

"Danger" level, will determine how bad the backfire could be if the user fails to concoct a recipe properly.

Factors include the number of ingredients, the length of the name of each ingredient, the user's effective level, the user's Int and the enchantment on the mixing device (aka "cauldron"). Higher values of 'danger' indicate more danger. Note that we assume that we have had the caster ready the alchemy skill *before *this routine is called. (no longer auto-readies that skill) -b.t.

Parameters:
casterwho is trying alchemy.
cauldroncontainer used.
rprecipe attempted.
Returns:
danger value.

Definition at line 783 of file alchemy.c.

References recipestruct::diff, FLAG_CURSED, FLAG_DAMNED, llevDebug, LOG(), MAX_BUF, QUERY_FLAG, snprintf(), and strtoint().

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* cauldron_sound ( void  ) [static]

Returns a random selection from cauldron_effect[].

Definition at line 87 of file alchemy.c.

References cauldron_effect, and rndm().

Referenced by alchemy_failure_effect(), and attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int content_recipe_value ( object *  op) [static]

Recipe value of the entire contents of a container.

This appears to just generate a hash value, which I guess for now works ok, but the possibility of duplicate hashes is certainly possible - msw

Parameters:
opcontained for which to generate a hash.
Returns:
hash value.

Definition at line 236 of file alchemy.c.

References llevDebug, LOG(), MAX_BUF, snprintf(), and strtoint().

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static recipe * find_recipe ( recipelist fl,
int  formula,
object *  ingredients 
) [static]

Find a recipe from a recipe list that matches the given formula.

If there is more than one matching recipe, it selects a random one. If at least one transmuting recipe matches, it only considers matching transmuting recipes.

Parameters:
fl?
formula?
ingredients?
Returns:
one matching recipe, or NULL if no recipe matches
Todo:
document parameters.

Definition at line 929 of file alchemy.c.

References recipestruct::arch_name, find_transmution_ob(), recipestruct::index, recipeliststruct::items, llevDebug, LOG(), recipestruct::next, rndm(), recipestruct::title, and recipestruct::transmute.

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static object * find_transmution_ob ( object *  first_ingred,
recipe rp,
size_t *  rp_arch_index,
int  create_item 
) [static]

Looks through the ingredient list.

If we find a suitable object in it - we will use that to make the requested artifact. Otherwise the code returns a 'generic' item if create_item is set. -b.t.

Parameters:
first_ingredpointer to first item to check
rprecipe the player is trying
rp_arch_indexpointer to return value; set to arch index for recipe; set to zero if not using a transmution formula
create_itemif set, will create a generic item if no suitable item is found.
Returns:
NULL if no suitable item was found and create_item is 0, existing or new item else.

Definition at line 450 of file alchemy.c.

References recipestruct::arch_name, recipestruct::arch_names, create_archetype(), llevDebug, LOG(), and recipestruct::transmute.

Referenced by find_recipe(), and make_item_from_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int is_defined_recipe ( const recipe rp,
const object *  cauldron,
object *  caster 
) [static]

Determines if ingredients in a container match the proper ingredients for a recipe.

This functions tries to find each defined ingredient in the container. It is the defined recipe iff

  • the number of ingredients of the recipe and in the container is equal
  • all ingredients of the recipe are found in the container
  • the number of batches is the same for all ingredients
Parameters:
rprecipe to check.
cauldroncontainer that holds the ingredients.
casterwho is trying to cast.
Returns:
1 if the ingredients match the recipe, 0 if not.

Definition at line 845 of file alchemy.c.

References recipestruct::ingred, MAX_BUF, linked_char::name, linked_char::next, and snprintf().

Referenced by attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static object * make_item_from_recipe ( object *  cauldron,
recipe rp 
) [static]

Using a list of items and a recipe to make an artifact.

Parameters:
cauldronthe cauldron (including the ingredients) used to make the item
rpthe recipe to make the artifact from
Returns:
the newly created object, NULL if something failed

Definition at line 398 of file alchemy.c.

References add_weight(), recipestruct::arch_name, find_transmution_ob(), FLAG_CURSED, FLAG_DAMNED, give_artifact_abilities(), artifactstruct::item, llevDebug, llevError, locate_recipe_artifact(), LOG(), QUERY_FLAG, SET_FLAG, sub_weight(), recipestruct::title, and transmute_materialname().

Referenced by attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

static int numb_ob_inside ( object *  op) [static]

Returns the total number of items in op, excluding ones in item's items.

Parameters:
opcontainer.
Returns:
total item count.

Definition at line 266 of file alchemy.c.

References llevDebug, and LOG().

Referenced by alchemy_failure_effect(), and attempt_do_alchemy().

Here is the call graph for this function:

Here is the caller graph for this function:

static void remove_contents ( object *  first_ob,
object *  save_item 
) [static]

All but object "save_item" are elimentated from the container list.

Note we have to becareful to remove the inventories of objects in the cauldron inventory (ex icecube has stuff in it).

Parameters:
first_obcontainer from which to remove.
save_itemwhat item to not remove. Can be NULL.

Definition at line 745 of file alchemy.c.

References free_object(), and remove_ob().

Referenced by alchemy_failure_effect(), and attempt_recipe().

Here is the call graph for this function:

Here is the caller graph for this function:

int use_alchemy ( object *  op)

Handle use_skill for alchemy-like items.

Parameters:
opplayer trying to do alchemy.
Returns:
1 if any recipe was attempted, 0 else.
Note:
Will inform player if attempting to use unpaid cauldron or ingredient.
Todo:
check if no superflous message when 2 cauldrons on same spot, one unpaid? (shouldn't happen, but well).

Definition at line 1006 of file alchemy.c.

References attempt_do_alchemy(), draw_ext_info_format(), esrv_send_inventory(), FLAG_APPLIED, FLAG_IS_CAULDRON, FLAG_UNPAID, GET_MAP_OB, MAX_BUF, MSG_TYPE_SKILL, MSG_TYPE_SKILL_ERROR, NDI_UNIQUE, query_base_name(), and QUERY_FLAG.

Referenced by do_skill().

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const char* const cauldron_effect[] [static]
Initial value:
 {
    "vibrates briefly",
    "produces a cloud of steam",
    "emits bright flames",
    "pours forth heavy black smoke",
    "emits sparks",
    "shoots out small flames",
    "whines painfully",
    "hiccups loudly",
    "wheezes",
    "burps",
    "shakes",
    "rattles",
    "makes chugging sounds",
    "smokes heavily for a while"
}

define this for some helpful debuging information

define this for loads of (marginal) debuging information Random cauldrons effects

Definition at line 55 of file alchemy.c.

Referenced by cauldron_sound().