Add throwable alchemist vials support

master
kts of kettek (nyaa) 2018-06-29 17:56:58 -07:00
parent fc24270545
commit 198f3e83b1
12 changed files with 123 additions and 11 deletions

View File

@ -579,6 +579,7 @@ void query_short_name(const object *op, char *buf, size_t size) {
case SCROLL:
case WAND:
case ROD:
case POTION:
if (QUERY_FLAG(op, FLAG_IDENTIFIED)||QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
if (!op->title) {
safe_strcat(buf, " of ", &len, size);
@ -784,6 +785,7 @@ void query_base_name(const object *op, int plural, char *buf, size_t size) {
case SCROLL:
case WAND:
case ROD:
case POTION:
if (QUERY_FLAG(op, FLAG_IDENTIFIED)||QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
if (!op->title) {
safe_strcat(buf, " of ", &len, size);
@ -1471,7 +1473,8 @@ void identify(object *op) {
if (QUERY_FLAG(op, FLAG_BLESSED))
SET_FLAG(op, FLAG_KNOWN_BLESSED);
if (op->type == POTION) {
/* we ignore POT_THROW since those have levels assigned */
if (op->type == POTION && op->subtype != POT_THROW) {
if (op->inv && op->randomitems) {
if (op->title)
free_string(op->title);

View File

@ -160,6 +160,7 @@ extern const char *const spellpathnames[NRSPELLPATHS];
#define POT_DUST 2
#define POT_FIGURINE 3
#define POT_BALM 4
#define POT_THROW 5
/*@}*/
/**

View File

@ -529,6 +529,7 @@ int pray(object *pl, object *skill);
void meditate(object *pl, object *skill);
int write_on_item(object *pl, const char *params, object *skill);
int skill_throw(object *op, object *part, int dir, const char *params, object *skill);
int do_throw(object *op, object *part, object *toss_item, int dir, object *skill);
/* skill_util.c */
void init_skills(void);
void link_player_skills(object *op);

View File

@ -1052,7 +1052,37 @@ cauldron cauldron
ingred booze,balm of first aid,red rose
#
# -- attack potion. Drinker/target is effected adversely
# -- @@ new vials of throwing that are probably better than anything below
Object NONE
arch vial_burning_hands
chance 4
diff 2
exp 250
yield 1
skill alchemy
cauldron cauldron
ingred empty vial,pile of cinnabar,pile of salt,pile of phosphorus,pile of sulphur
#
Object NONE
arch vial_explosion
chance 4
diff 3
exp 350
yield 1
skill alchemy
cauldron cauldron
ingred empty vial,pile of salt,pile of phosphorus,pile of sulphur
#
Object NONE
arch vial_sparkshower
chance 4
diff 1
exp 150
yield 1
skill alchemy
cauldron cauldron
ingred empty vial,pile of pyrite,pile of salt,pile of phosphorus,pile of sulphur
# -- old stuff
# -- sm. lightning
Object electric shock
arch potion_generic

View File

@ -194,7 +194,7 @@ static void attempt_do_alchemy(object *caster, object *cauldron) {
/* create the object **FIRST**, then decide whether to keep it. */
if ((item = attempt_recipe(caster, cauldron, ability, rp, formula/rp->index, attempt_shadow_alchemy)) != NULL) {
/* compute base chance of recipe success */
success_chance = ((float)ability/(float)(rp->diff*(item->level+2)));
success_chance = ((float)(ability*2)/(float)(rp->diff*(item->level+2)));
if (ave_chance == 0)
ave_chance = 1;
@ -344,7 +344,7 @@ static object *attempt_recipe(object *caster, object *cauldron, int ability, rec
if ((item = make_item_from_recipe(cauldron, rp)) != NULL) {
remove_contents(cauldron->inv, item);
/* adj lvl, nrof on caster level */
/* adj lvl, nrof, and enhancement on caster level */
adjust_product(item, ability, rp->yield ? (rp->yield*batches) : batches);
if (!item->env && (item = insert_ob_in_ob(item, cauldron)) == NULL) {
draw_ext_info(NDI_UNIQUE, 0, caster, MSG_TYPE_SKILL, MSG_TYPE_SKILL_FAILURE,
@ -383,6 +383,11 @@ static void adjust_product(object *item, int lvl, int yield) {
nrof = yield;
item->nrof = nrof;
}
// @@ We're also adding the player's level to the item so that potions and similar can level over time.
if (item->type == POTION && item->subtype == POT_THROW) {
LOG(llevError, "making alchemy with %d\n", lvl);
item->level = lvl;
}
}
/**

View File

@ -1835,6 +1835,14 @@ void apply_changes_to_player(object *pl, object *change) {
pl->slaying = join_strings(pl->slaying, change->slaying, ",");
}
/* modify the player's attunement */
if (change->path_attuned) {
if (pl->path_attuned)
pl->path_attuned |= change->path_attuned;
else
pl->path_attuned = change->path_attuned;
}
/* set up the face, for some races. */
/* first, look for the force object banning changing the

View File

@ -741,6 +741,7 @@ static int abort_attack(object *target, object *hitter, int simple_attack) {
}
static void thrown_item_effect(object *, object *);
static void thrown_potion_effect(object *);
/**
* Handles simple attack cases.
@ -2435,8 +2436,10 @@ static void thrown_item_effect(object *hitter, object *victim) {
*/
switch (hitter->type) {
case POTION:
if (hitter->subtype == POT_THROW) {
thrown_potion_effect(hitter);
/* should player get a save throw instead of checking magic protection? */
if (QUERY_FLAG(victim, FLAG_ALIVE)
} else if (QUERY_FLAG(victim, FLAG_ALIVE)
&& !QUERY_FLAG(victim, FLAG_UNDEAD)
&& (victim->resist[ATNR_MAGIC] < 60))
(void)ob_apply(hitter, victim, 0);
@ -2459,6 +2462,25 @@ static void thrown_item_effect(object *hitter, object *victim) {
}
}
static void thrown_potion_effect(object *throw_ob) {
LOG(llevError, "OKAY, HERE IS POTION EFFECT\n");
object *op, *spob;
spob = throw_ob->inv;
op = get_owner(throw_ob);
if (op->type == PLAYER && spob)
draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
"Your vial releases %s.",
"Your vial releases %s.",
spob->name);
cast_spell(op, throw_ob, throw_ob->direction, spob, NULL);
if (!QUERY_FLAG(throw_ob, FLAG_REMOVED))
remove_ob(throw_ob);
free_object(throw_ob);
}
/**
* Adjustments to attack rolls by various conditions
* @param hitter

View File

@ -758,6 +758,8 @@ void give_initial_items(object *pl, treasurelist *items) {
SET_FLAG(op, FLAG_CAN_USE_SKILL);
op->stats.exp = 0;
op->level = 1;
} else if (op->type == POTION && op->subtype == POT_THROW) {
/* don't lock, etc. */
}
/* lock all 'normal items by default */
else

View File

@ -1903,7 +1903,7 @@ static object *make_throw_ob(object *orig) {
* skill was successfully used.
* @todo this messy function should probably be simplified.
*/
static int do_throw(object *op, object *part, object *toss_item, int dir, object *skill) {
int do_throw(object *op, object *part, object *toss_item, int dir, object *skill) {
object *throw_ob = toss_item, *left = NULL;
tag_t left_tag;
int eff_str = 0, maxc, str = op->stats.Str, dam = 0;
@ -2027,6 +2027,8 @@ static int do_throw(object *op, object *part, object *toss_item, int dir, object
return 1;
}
/* record the direction it was thrown in */
throw_ob->direction = dir;
/* Make a thrown object -- insert real object in a 'carrier' object.
* If unsuccessfull at making the "thrown_obj", we just reinsert
* the original object back into inventory and exit

View File

@ -454,16 +454,28 @@ int cast_cone(object *op, object *caster, int dir, object *spell) {
continue;
}
x = op->x+freearr_x[d];
y = op->y+freearr_y[d];
/* Special handling for making the spell emit from a thrown
* potion's location
*/
if (caster->type == POTION && caster->subtype == POT_THROW) {
x = caster->x+freearr_x[d];
y = caster->y+freearr_y[d];
if (get_map_flags(op->map, &m, x, y, &sx, &sy)&P_OUT_OF_MAP)
if (get_map_flags(caster->map, &m, x, y, &sx, &sy)&P_OUT_OF_MAP)
continue;
} else {
x = op->x+freearr_x[d];
y = op->y+freearr_y[d];
if (get_map_flags(op->map, &m, x, y, &sx, &sy)&P_OUT_OF_MAP)
continue;
}
if ((movetype&GET_MAP_MOVE_BLOCK(m, sx, sy)) == movetype)
continue;
success = 1;
tmp = arch_to_object(spell->other_arch);
set_owner(tmp, op);
set_spell_skill(op, caster, spell, tmp);

View File

@ -333,6 +333,11 @@ int SP_level_dam_adjust(const object *caster, const object *spob) {
int level = caster_level(caster, spob);
int adj = level-min_casting_level(caster, spob);
/* do 25% more damage with thrown potions */
if (caster->type == POTION && caster->subtype == POT_THROW) {
adj *= 1.25f;
}
if (adj < 0)
adj = 0;
if (spob->dam_modifier)
@ -358,6 +363,11 @@ int SP_level_duration_adjust(const object *caster, const object *spob) {
int level = caster_level(caster, spob);
int adj = level-min_casting_level(caster, spob);
/* last 50% longer with thrown potions */
if (caster->type == POTION && caster->subtype == POT_THROW) {
adj *= 1.50f;
}
if (adj < 0)
adj = 0;
if (spob->duration_modifier)
@ -384,6 +394,11 @@ int SP_level_range_adjust(const object *caster, const object *spob) {
int level = caster_level(caster, spob);
int adj = level-min_casting_level(caster, spob);
/* go -25% further with thrown potions */
if (caster->type == POTION && caster->subtype == POT_THROW) {
adj *= .75f;
}
if (adj < 0)
adj = 0;
if (spob->range_modifier)
@ -1525,7 +1540,6 @@ int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stri
} else if (caster->type == WAND
|| caster->type == HORN
|| caster->type == ROD
|| caster->type == POTION
|| caster->type == SCROLL) {
op->speed_left -= 2*FABS(op->speed);
}
@ -1568,6 +1582,9 @@ int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stri
skill = find_skill_by_name(owner, caster->skill);
}
if (caster->type == POTION && caster->subtype == POT_THROW) {
}
if (confusion_effect) {
/* If we get here, the confusion effect was 'random effect', so do it and bail out. */
draw_ext_info_format(NDI_UNIQUE, 0, op,

View File

@ -171,8 +171,17 @@ static method_ret potion_type_apply(ob_methods *context, object *potion,
fball->x = applier->x;
fball->y = applier->y;
insert_ob_in_map(fball, applier->map, NULL, 0);
} else
cast_spell(applier, potion, applier->facing, potion->inv, NULL);
} else if (potion->subtype == POT_THROW) {
/* FIXME: This doesn't really work. We want vials to automatically
* be thrown when the player applies them.
*/
object* skop = find_skill_by_name(applier, skill_names[SK_THROWING]);
if (skop) {
do_throw(applier, applier, potion, applier->direction, skop);
}
} else {
cast_spell(applier, potion, potion->direction, potion->inv, NULL);
}
decrease_ob(potion);
/* if youre dead, no point in doing this... */