diff options
author | DracoOmega <draco_omega@live.com> | 2014-02-25 07:21:30 -0330 |
---|---|---|
committer | Steve Melenchuk <smelenchuk@gmail.com> | 2014-03-06 09:58:10 -0700 |
commit | 2a0814e80e4265e48f4a64bdc9eff03199f80c2f (patch) | |
tree | db7dfb24b59ad76cc25edd9bd40aa2cee4e9b1f3 /crawl-ref/source/ghost.cc | |
parent | 5112a529f80abc0ff50deb9ed1cb59b1f15397f6 (diff) | |
download | crawl-ref-2a0814e80e4265e48f4a64bdc9eff03199f80c2f.tar.gz crawl-ref-2a0814e80e4265e48f4a64bdc9eff03199f80c2f.zip |
New spell: Spellforged Servitor
With the idea of introducing more summoning spells that a bit
unique in some way, this is a level 7 Summoning/Conjurations spell
which summons a single golem-like being that possesses a subset of
the caster's own conjurations.
The spell list is assembled deterministically, somewhat similar to
player ghosts (though different in a number of regards). The first
3 spell slots draw from a 'primary' list containing direct
conjurations like bolt of cold or poison arrow, while the next 2
are from a 'secondary' list which tends to contain AoE effects and
cloud spells, as well as things like airstrike. Spells are selected
roughly in order of level and power, with the player's higher spell
skills having a small effect. In practice, I think the servitor
will fairly transparently possess a selection of the player's better
spells, without anyone needing to think much on how it arrived at
this list.
Many of the highest level spells (like fire storm and shatter) are
excluded not only for power reasons, but also because a servitor
using these could be downright dangerous to its caster. The main
exception I made here was CBL, which is allowed (being both
lower-level and often similarly dangerous when the player uses it,
though I open to changing this).
Diffstat (limited to 'crawl-ref/source/ghost.cc')
-rw-r--r-- | crawl-ref/source/ghost.cc | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc index 5d56eacfb2..0418dff169 100644 --- a/crawl-ref/source/ghost.cc +++ b/crawl-ref/source/ghost.cc @@ -20,6 +20,7 @@ #include "random.h" #include "skills2.h" #include "spl-cast.h" +#include "spl-util.h" #include "mon-util.h" #include "mon-transit.h" #include "player.h" @@ -1044,3 +1045,130 @@ int ghost_level_to_rank(const int xl) if (xl < 27) return 6; return 7; } + +static spell_type servitor_spells_primary[] = +{ + SPELL_LEHUDIBS_CRYSTAL_SPEAR, + SPELL_IOOD, + SPELL_IRON_SHOT, + SPELL_BOLT_OF_FIRE, + SPELL_BOLT_OF_COLD, + SPELL_POISON_ARROW, + SPELL_LIGHTNING_BOLT, + SPELL_BOLT_OF_MAGMA, + SPELL_VENOM_BOLT, + SPELL_THROW_ICICLE, + SPELL_ISKENDERUNS_MYSTIC_BLAST, + SPELL_NO_SPELL, // end search +}; + +static spell_type servitor_spells_secondary[] = +{ + SPELL_CONJURE_BALL_LIGHTNING, + SPELL_FIREBALL, + SPELL_AIRSTRIKE, + SPELL_LRD, + SPELL_FREEZING_CLOUD, + SPELL_POISONOUS_CLOUD, + SPELL_FORCE_LANCE, + SPELL_MEPHITIC_CLOUD, + SPELL_NO_SPELL, // end search +}; + +static spell_type servitor_spells_fallback[] = +{ + SPELL_STONE_ARROW, + SPELL_STICKY_FLAME, + SPELL_THROW_FLAME, + SPELL_THROW_FROST, + SPELL_FREEZE, + SPELL_FLAME_TONGUE, + SPELL_STING, + SPELL_SANDBLAST, + SPELL_MAGIC_DART, + SPELL_NO_SPELL, // end search +}; + +static spell_type _best_aligned_spell(vector<spell_type> spells, skill_type skill) +{ + for (unsigned int i = 0; i < spells.size(); ++i) + { + if (spell_typematch(spells[i], skill)) + return spells[i]; + } + + // If we couldn't find any that match, just pick the first one + return spells[0]; +} + +// Select servitor spells based on those known to the player +// (Primary determines whether we are populating the first 3 or next 2 slots) +bool ghost_demon::populate_servitor_spells(spell_type* spell_list, bool primary, + skill_type primary_skill) +{ + vector<spell_type> candidates; + const unsigned int num = (primary ? 3 : 2); + const unsigned int offset = (primary ? 0 : 3); + + int i = 0; + spell_type spell = SPELL_NO_SPELL; + while ((spell = spell_list[i++]) != SPELL_NO_SPELL) + { + if (_know_spell(spell)) + candidates.push_back(spell); + } + + if (candidates.size() >= num) + { + for (unsigned int j = offset; j < offset + num; ++j) + spells[j] = candidates[j - offset]; + } + else if (candidates.size() > 0) + { + // Choose the highest-level spell best aligned with our spell + // skills to duplicate + const spell_type copy_spell = _best_aligned_spell(candidates, + primary_skill); + + for (unsigned int j = offset; j < offset + num; ++j) + { + if (candidates.size() > j - offset) + spells[j] = candidates[j - offset]; + else + spells[j] = copy_spell; + } + } + + return (candidates.size() > 0); +} + +void ghost_demon::init_spellforged_servitor() +{ + // Determine highest magic skill (used for solving some tie-breakers) + skill_type best_magic_skill = NUM_SKILLS; + int skill_level = -1; + for (int i = SK_FIRE_MAGIC; i <= SK_POISON_MAGIC; ++i) + { + if (you.skill((skill_type)i) >= skill_level) + { + skill_level = you.skill((skill_type)i); + best_magic_skill = (skill_type)i; + } + } + + int pow = calc_spell_power(SPELL_SPELLFORGED_SERVITOR, true); + + speed = 10; + ev = 10; + ac = 10; + xl = 9 + (pow/16); + max_hp = 80; + spellcaster = true; + damage = 0; + att_type = AT_NONE; + + // Give the servitor its spells + if (!populate_servitor_spells(servitor_spells_primary, true, best_magic_skill)) + populate_servitor_spells(servitor_spells_fallback, true, best_magic_skill); + populate_servitor_spells(servitor_spells_secondary, false, best_magic_skill); +} |