/*
** potion.c - potion information object
**
** This object will contain the information related to a particular
** potion. It is intended to be used as a base for virtual objects
** which will be cloned by the potion handler (ie, only one virtual
** object for each potion will exist in the game). The info on the
** potion will be gotten by querying the potion handler.
**
** Parameters:
** min_level - minimum aggregate level for success
** max_level - aggregate level at which success is certain
** advance_chance - chance of advancing skill(s) when successful
** backfire_chance - chance of result being other than expected
** rel_strength - amount of reagent will be
** aggregate_sum*rel_strength/min_level
** skills - array of skills required and weighting
** reagent_alias - medium alias for resulting reagent (on success)
** backfire_alias - medium alias for resulting reagent (on backfire)
** potion_verb - verb expected for this potion (eg, 'mix', 'brew')
** recipe - the text of the recipe for the potion
** chant - the chant spoken by the player (optional)
**
** Written by Jeremy, ?/?/95
*/
// I'm wondering if I really need this...
inherit "/std/object";
#include <tasks.h>
#define SKILL_WGT 0
#define SKILL_MAX 1
#define SKILL_LVL 2
#define SKILL_ADV 3
#define REAGENTS "/obj/reagents/"
int min_level, max_level, advance_chance, backfire_chance, rel_strength;
mapping skills = allocate_mapping(1);
string *skill_str, reagent_alias, backfire_alias, potion_verb, recipe;
string chant;
void set_min_level(int l) { min_level = l; }
void set_max_level(int l) { max_level = l; }
int query_min_level() { return min_level; }
int query_max_level() { return max_level; }
void set_advance_chance(int c) { advance_chance = c; }
int query_advance_chance() { return advance_chance; }
void set_backfire_chance(int c) { backfire_chance = c; }
int query_backfire_chance() { return backfire_chance; }
void set_reagent_alias(string s) { reagent_alias = s; }
string query_reagent_alias() { return reagent_alias; }
void set_backfire_alias(string s) { backfire_alias = s; }
string query_backfire_alias() { return backfire_alias; }
void set_rel_strength(int s) { rel_strength = s; }
int query_rel_strength() { return rel_strength; }
void set_potion_verb(string s) { potion_verb = s; }
string query_potion_verb() { return potion_verb; }
void set_recipe(string s) { recipe = s; }
string query_recipe() { return recipe; }
void set_chant(string s) { chant = s; }
string query_chant() { return chant; }
// The final determination of success/failure is a weighted sum of
// one or more skill levels or bonuses. Each element of 's' is a
// 4-element array: the skill (string), the weight (int), and whether to use
// level or bonus (true=level). 'skills' is a mapping, with the key
// being the skill and the value being a 4-element array: the remaining
// 3 and a flag indicating if the skill should be advanced for this player.
void set_skills(mixed s) {
int i;
for (i = 0; i < (sizeof(s)); i++) {
skills[s[i][0]] = ({s[i][SKILL_WGT+1], s[i][SKILL_MAX+1],
s[i][SKILL_LVL+1], 0});
}
skill_str = keys(skills);
}
mapping query_skills() { return skills; }
// This is the guts of the potion. If successful, it'll return an
// object that'll react with the other reagents in the vessel.
object clone_reagent(string given_verb) {
int result, i, sum, x;
string s;
object ob;
if (potion_verb != given_verb) return 0;
for (i = 0; i < sizeof(skill_str); i++) {
s = skill_str[i];
skills[s][SKILL_ADV] = 0;
if (skills[s][SKILL_LVL]) {
if ((x = (int)this_player()->query_skill(s))
> skills[s][SKILL_MAX]) {
x = skills[s][SKILL_MAX];
} else {
skills[s][SKILL_ADV] = 1;
}
} else {
if ((x = (int)this_player()->query_skill_bonus(s))
> skills[s][SKILL_MAX]) {
x = skills[s][SKILL_MAX];
} else {
skills[s][SKILL_ADV] = 1;
}
}
sum += x * skills[s][SKILL_WGT];
}
//write("sum = " + sum + "\n");
result = TASKER->attempt_task(min_level, sum, advance_chance,
(max_level - min_level));
if ((result == FAIL) || (result == BARF)) {
if (random(100) < backfire_chance) {
// Spell backfired
ob = clone_object(REAGENTS+"brew_reagent.ob");
ob->set_medium_alias(backfire_alias);
ob->set_amount(sum*rel_strength/min_level);
return ob;
}
return 0;
}
if (result == AWARD) {
for (i = 0; i < sizeof(skill_str); i++) {
s = skill_str[i];
if (skills[s][SKILL_ADV]) {
this_player()->add_skill_level(s, 1, 0);
}
}
}
ob = clone_object(REAGENTS+"brew_reagent.ob");
ob->set_medium_alias(reagent_alias);
ob->set_amount(sum*rel_strength/min_level);
return ob;
}