 |
Crossfire Server, Trunk
1.75.0
|
Go to the documentation of this file.
41 #define EXTREME_ALCHEMY_DEBUG
47 "produces a cloud of steam",
48 "emits bright flames",
49 "pours forth heavy black smoke",
51 "shoots out small flames",
58 "makes chugging sounds",
59 "smokes heavily for a while"
68 static object *
attempt_recipe(
object *caster,
object *cauldron,
int ability,
const recipe *rp,
int nbatches,
int ignore_cauldron);
91 return MAX(.01, .3 - (diff - 10) * .03);
94 return .5 + .02 * (float)(-diff);
96 return MIN(.95, .70 + (-diff - 10) * .01);
126 const int cauldron_add_skill = (cauldron->
magic + 1) / 2;
127 const int eff_skill =
skill->level + cauldron_add_skill;
162 float success_chance;
163 int numb, ability = 1;
184 if (strcmp(rp->
title,
"NONE"))
191 LOG(
llevDebug,
"WIZ couldn't find formula for ingredients.\n");
198 uint64_t value_ingredients;
200 int attempt_shadow_alchemy;
203 if (rp->
skill != NULL) {
207 "You do not have the proper skill for this recipe");
209 ability += skop->
level*((4.0+cauldron->
magic)/4.0);
223 "You aren't skilled enough to try this recipe.");
228 value_ingredients = 0;
236 if ((item =
attempt_recipe(caster, cauldron, ability, rp, formula/rp->
index, attempt_shadow_alchemy)) != NULL) {
241 LOG(
llevDebug,
"percent success chance = %f ab%d / diff%d*lev%d\n", success_chance, ability, rp->
diff, item->
level);
245 if (attempt_shadow_alchemy && value_item > value_ingredients) {
248 LOG(
llevDebug,
"Forcing failure for shadow alchemy recipe because price of ingredients (%llu) is less than price of result (%llu).\n", value_ingredients, value_item);
250 LOG(
llevDebug,
"Forcing failure for shadow alchemy recipe because price of ingredients (%I64d) is less than price of result (%I64d).\n", value_ingredients, value_item);
277 int tval = 0, formula = 0;
283 snprintf(
name,
sizeof(
name),
"%s %s", tmp->name, tmp->title);
310 LOG(
llevDebug,
"numb_ob_inside(%s): found %d ingredients\n", op->
name, o_number);
340 static object *
attempt_recipe(
object *caster,
object *cauldron,
int ability,
const recipe *rp,
int nbatches,
int ignore_cauldron) {
341 object *item = NULL, *skop;
343 int batches = abs(nbatches);
346 if (!ignore_cauldron && (strcmp(rp->
cauldron, cauldron->
arch->
name) != 0)) {
348 "You are not using the proper facilities for this formula.");
364 "You know the ingredients, but not the technique. Go learn how to do this recipe.");
369 #ifdef EXTREME_ALCHEMY_DEBUG
370 LOG(
llevDebug,
"attempt_recipe(): got %d nbatches\n", nbatches);
385 "Nothing happened.");
414 nrof = (1.0-1.0/(adjust/10.0+1.0))*(
rndm(0, yield-1)+
rndm(0, yield-1)+
rndm(0, yield-1))+1;
434 size_t rp_arch_index;
437 return (
object *)NULL;
441 LOG(
llevDebug,
"make_alchemy_item(): failed to create alchemical object.\n");
442 return (
object *)NULL;
446 if (item->
env != NULL)
450 if (strcmp(rp->
title,
"NONE")) {
451 int item_power_delta = 0;
453 LOG(
llevError,
"make_alchemy_item(): failed to locate recipe artifact.\n");
455 return (
object *)NULL;
471 if (item->
env != NULL)
512 if (i < rp->arch_names)
519 if (create_item && (!item || item->
nrof > 1)) {
553 if (!op || !cauldron)
591 if (!(material&inv->material))
592 material |= inv->material;
614 }
else if (
level < 40) {
631 if ((tmp = cauldron->
inv)) {
649 }
while (
rndm(0, 2));
683 }
else if (
level < 50) {
687 switch (
rndm(0, 2)) {
693 "The %s creates a bomb!",
702 "The %s erupts in flame!",
708 }
else if (
level < 60) {
713 }
else if (
level < 80) {
720 "The %s erupts in flame!",
723 }
else if (
level < 100) {
734 "Your %s turns darker then makes a gulping sound!",
738 "Your %s becomes darker.",
741 }
else if (
level < 110) {
749 "The %s %s and then pours forth monsters!",
752 }
else if (
level < 150) {
753 int roll =
rndm(1, 3);
759 }
else if (
level == 151) {
782 "You unwisely release potent forces!");
803 if (tmp != save_item) {
840 danger -= cauldron->
magic;
858 danger += rp->
diff*3;
867 LOG(
llevDebug,
"calc_alch_danger() returned danger=%d\n", danger);
891 uint32_t batches_in_cauldron;
897 for (ingredient = rp->
ingred; ingredient != NULL; ingredient = ingredient->
next)
901 LOG(
llevDebug,
"cauldron %s, item %s, number %d->%d\n", cauldron->
name, ob->name, number, number - 1);
909 batches_in_cauldron = 0;
910 for (ingredient = rp->
ingred; ingredient != NULL; ingredient = ingredient->
next) {
918 while (isdigit(*
name)) {
919 nrof = 10*nrof+(*
name-
'0');
933 if (ob->title == NULL)
936 snprintf(name_ob,
sizeof(name_ob),
"%s %s", ob->name, ob->title);
940 if (strcmp(name2,
name) == 0) {
941 if (ob->nrof%nrof == 0) {
945 batches = (ob->nrof ? ob->nrof : 1)/nrof;
947 LOG(
llevDebug,
"batches of ingred %s: %d; batches prior: %d\n",
name, batches, batches_in_cauldron);
949 if (batches_in_cauldron == 0) {
950 batches_in_cauldron = batches;
952 }
else if (batches_in_cauldron == batches)
982 int recipes_matching;
984 size_t rp_arch_index;
986 #ifdef EXTREME_ALCHEMY_DEBUG
990 recipes_matching = 0;
992 for (rp = fl->
items; rp != NULL; rp = rp->
next) {
995 #ifdef EXTREME_ALCHEMY_DEBUG
1001 object *ingredients = cauldron->
inv;
1003 #ifdef EXTREME_ALCHEMY_DEBUG
1007 if (!transmute_found) {
1008 transmute_found = 1;
1009 recipes_matching = 0;
1011 }
else if (transmute_found) {
1012 #ifdef EXTREME_ALCHEMY_DEBUG
1018 #ifdef EXTREME_ALCHEMY_DEBUG
1024 if (
rndm(0, recipes_matching) == 0)
1030 if (result == NULL) {
1031 #ifdef ALCHEMY_DEBUG
1032 LOG(
llevDebug,
"couldn't find formula for ingredients.\n");
1037 #ifdef ALCHEMY_DEBUG
1038 if (strcmp(result->
title,
"NONE") != 0)
1058 object *unpaid_cauldron = NULL;
1059 object *unpaid_item = NULL;
1060 int did_alchemy = 0;
1069 unpaid_cauldron = tmp;
1073 if (unpaid_item != NULL)
1082 if (unpaid_cauldron) {
1085 "You must pay for your %s first!",
1087 }
else if (unpaid_item) {
1090 "You must pay for your %s first!",
sstring name_pl
The plural name of the object.
static int calc_alch_danger(object *caster, object *cauldron, const recipe *rp)
"Danger" level, will determine how bad the backfire could be if the user fails to concoct a recipe pr...
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
recipelist * get_formulalist(int i)
Gets a formula list by ingredients count.
@ llevError
Error, serious thing.
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
static const char * cauldron_sound(void)
Returns a random selection from cauldron_effect[].
object * inv
Pointer to the first object in the inventory.
#define MSG_TYPE_SKILL
Messages related to skill use.
#define QUERY_FLAG(xyz, p)
size_t arch_names
Size of the arch_name[] array.
int yield
Maximum number of items produced by the recipe.
uint64_t price_base(const object *obj)
Determine the base (intrinsic) value of an item.
void esrv_send_inventory(object *pl, object *op)
Sends inventory of a container.
int8_t item_power
Power rating of the object.
struct archetype * arch
Pointer to archetype.
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
static const recipe * find_recipe(const recipelist *fl, int formula, object *cauldron)
Find a recipe from a recipe list that matches the given formula.
sstring failure_arch
Arch of the item to generate on failure, instead of blowing up stuff.
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
struct mapstruct * map
Pointer to the map in which this object is present.
static const char *const cauldron_effect[]
define this for some helpful debuging information
object * item
Special values of the artifact.
recipe * items
Pointer to first recipe in this list.
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
static void alchemy_failure_effect(object *op, object *cauldron, const recipe *rp, int danger)
Ouch.
sstring failure_message
Specific failure message.
char ** arch_name
Possible archetypes of the final product made.
static object * attempt_recipe(object *caster, object *cauldron, int ability, const recipe *rp, int nbatches, int ignore_cauldron)
Essentially a wrapper for make_item_from_recipe() and object_insert_in_ob().
int transmute
If defined, one of the formula ingredients is used as the basis for the product object.
int rndm(int min, int max)
Returns a number between min and max.
int fire_arch_from_position(object *op, object *caster, int16_t x, int16_t y, int dir, object *spell)
Fires an archetype.
sstring title
Of foo, etc.
#define SK_EXP_NONE
Player gets nothing.
int exp
How much exp to give for this formulae.
#define FLAG_APPLIED
Object is ready for use by living.
int16_t level
Level of creature or object.
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
#define FLAG_NO_PICK
Object can't be picked up.
Plugin animator file specs[Config] name
void cast_magic_storm(object *op, object *tmp, int lvl)
This is really used mostly for spell fumbles and the like.
int16_t y
Position in the map for this object.
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
static uint32_t NROF(const object *const ob)
Returns ob->nrof, unless it is 0, in which case return 1.
static object * find_transmution_ob(object *first_ingred, const recipe *rp, size_t *rp_arch_index, int create_item)
Looks through the ingredient list.
List of recipes with a certain number of ingredients.
#define FLAG_KNOWN_CURSED
The object is known to be cursed.
#define MSG_TYPE_COMMAND_DM
DM related commands.
object clone
An object from which to do object_copy()
sstring add_string(const char *str)
This will add 'str' to the hash table.
#define FOR_OB_AND_BELOW_FINISH()
Finishes FOR_OB_AND_BELOW_PREPARE().
int use_alchemy(object *op)
Handle use_skill for alchemy-like items.
static int numb_ob_inside(const object *op)
Returns the total number of items in op, excluding ones in item's items.
#define SP_MED_FIREBALL
These are some hard coded values that are used within the code for spell failure effects or pieces of...
int32_t value
How much money it is worth (or contains)
int is_identified(const object *op)
Return true if the item is identified, either because it is of a type that doesn't ever need identifi...
uint8_t type
PLAYER, BULLET, etc.
int index
Index value derived from formula ingredients.
#define FLAG_DAMNED
The object is very cursed.
int16_t dam
How much damage this object does when hitting.
int8_t magic
Any magical bonuses to this item.
sstring materialname
Specific material name.
static int content_recipe_value(object *op)
Recipe value of the entire contents of a container.
object * object_find_by_flag(const object *who, int flag)
Find object in inventory by flag.
struct linked_char * next
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
#define FLAG_CAN_ROLL
Object can be rolled.
#define MSG_TYPE_SKILL_MISSING
Don't have the skill.
void change_exp(object *op, int64_t exp, const char *skill_name, int flag)
Changes experience to a player/monster.
static void remove_contents(object *first_ob, object *save_item)
All but object "save_item" are elimentated from the container list.
#define FOR_OB_AND_BELOW_PREPARE(op_)
Constructs a loop iterating over an object and all objects below it in the same pile.
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
TIPS on SURVIVING Crossfire is populated with a wealth of different monsters These monsters can have varying immunities and attack types In some of them can be quite a bit smarter than others It will be important for new players to learn the abilities of different monsters and learn just how much it will take to kill them This section discusses how monsters can interact with players Most monsters in the game are out to mindlessly kill and destroy the players These monsters will help boost a player s after he kills them When fighting a large amount of monsters in a single attempt to find a narrower hallway so that you are not being attacked from all sides Charging into a room full of Beholders for instance would not be open the door and fight them one at a time For there are several maps designed for them Find these areas and clear them out All throughout these a player can find signs and books which they can read by stepping onto them and hitting A to apply the book sign These messages will help the player to learn the system One more always keep an eye on your food If your food drops to your character will soon so BE CAREFUL ! NPCs Non Player Character are special monsters which have intelligence Players may be able to interact with these monsters to help solve puzzles and find items of interest To speak with a monster you suspect to be a simply move to an adjacent square to them and push the double ie Enter your and press< Return > You can also use say if you feel like typing a little extra Other NPCs may not speak to but display intelligence with their movement Some monsters can be and may attack the nearest of your enemies Others can be in that they follow you around and help you in your quest to kill enemies and find treasure SPECIAL ITEMS There are many special items which can be found in of these the most important may be the signs all a player must do is apply the handle In the case of the player must move items over the button to hold it down Some of the larger buttons may need very large items to be moved onto before they can be activated Gates and locked but be for you could fall down into a pit full of ghosts or dragons and not be able to get back out Break away sometimes it may be worth a player s time to test the walls of a map for secret doors Fire such as missile weapons and spells you will notice them going up in smoke ! So be careful not to destroy valuable items Spellbooks sometimes a player can learn the other times they cannot There are many different types of books and scrolls out there Improve item have lower weight
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level,...
#define MAX_BUF
Used for all kinds of things.
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
int32_t weight
Attributes of the object.
static void attempt_do_alchemy(object *caster, object *cauldron)
Main part of the ALCHEMY code.
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
static object * make_item_from_recipe(object *cauldron, const recipe *rp)
Using a list of items and a recipe to make an artifact.
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
void object_add_weight(object *op, signed long weight)
object_add_weight(object, weight) adds the specified weight to an object, and also updates how much t...
object * object_find_by_type_and_slaying(const object *who, int type, const char *slaying)
Find object in inventory by type and slaying.
#define FLAG_WIZ
Object has special privilegies.
#define MSG_TYPE_SKILL_ERROR
Doing something wrong.
#define NDI_UNIQUE
Print immediately, don't buffer.
void transmute_materialname(object *op, const object *change)
When doing transmutation of objects, we have to recheck the resistances, as some that did not apply p...
sstring name
The name of the object, obviously...
#define MSG_TYPE_SKILL_FAILURE
Failure in using skill.
recipe * get_random_recipe(recipelist *rpl)
Gets a random recipe from a list, based on chance.
const artifact * locate_recipe_artifact(const recipe *rp, size_t idx)
Finds an artifact for a recipe.
void change_attr_value(living *stats, int attr, int8_t value)
Like set_attr_value(), but instead the value (which can be negative) is added to the specified stat.
object * env
Pointer to the object which is the environment.
void monster_npc_call_help(object *op)
A monster calls for help against its enemy.
int summon_hostile_monsters(object *op, int n, const char *monstername)
Summons hostile monsters and places them in nearby squares.
static int is_defined_recipe(const recipe *rp, const object *cauldron)
Determines if ingredients in a container match the proper ingredients for a recipe.
int strtoint(const char *buf)
Convert buf into an integer equal to the coadded sum of the (lowercase) character.
int diff
Alchemical dfficulty level.
#define CLEAR_FLAG(xyz, p)
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
sstring keycode
Optional keycode needed to use the recipe.
int min_level
Minimum level to have in the skill to be able to use the formulae.
object * get_random_mon(int level)
Returns a random monster selected from linked list of all monsters in the current game.
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
linked_char * ingred
List of ingredients.
static float chance_fn(int diff)
Compute a success probability, between .01 and .95, based on the level difference.
#define FLAG_UNPAID
Object hasn't been paid for yet.
sstring name
More definite name, like "generate_kobold".
uint32_t nrof
Number of objects.
recipe * next
Next recipe with the same number of ingredients.
sstring skill
Skill name used to make this recipe.
void query_base_name(const object *op, int plural, char *buf, size_t size)
Query a short name for the item.
living stats
Str, Con, Dex, etc.
This is one artifact, ie one special item.
#define MSG_TYPE_SKILL_SUCCESS
Successfully used skill.
#define FLAG_IS_CAULDRON
container can make alchemical stuff
void object_sub_weight(object *op, signed long weight)
Recursively (outwards) subtracts a number from the weight of an object (and what is carried by it's e...
static float recipe_chance(const recipe *rp, const object *skill, const object *cauldron)
Compute the success probability of a recipe.
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 cas...
#define FLAG_CURSED
The object is cursed.
void generate_artifact(object *op, int difficulty)
Decides randomly which artifact the object should be turned into.
uint16_t material
What materials this object consist of.
MoveType move_block
What movement types this blocks.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
@ llevDebug
Only for debugging purposes.
#define FLAG_IDENTIFIED
Player knows full info about item.
sstring cauldron
Arch of the cauldron/workbench used to house the formulae.
sstring title
Distinguishing name of product.