Add Warlock class: pact-bound debuff and DoT caster#519
Add Warlock class: pact-bound debuff and DoT caster#519aconite33 wants to merge 6 commits intoTempusMUD:mainfrom
Conversation
Introduces a new playable class, the Warlock, occupying the former
CLASS_SPARE1 slot. Warlocks are an evil-only fantasy caster whose
identity is debuffs and damage-over-time, anchored by an at-will
signature attack called Eldritch Blast.
Class shell:
- CLASS_SPARE1 renamed to CLASS_WARLOCK (enum value 14).
- IS_SPARE1 renamed to IS_WARLOCK; ITEM3_REQ_SPARE1 renamed to
ITEM3_REQ_WARLOCK (bit value preserved, no data migration needed).
- prac_params, race_restr, thaco_factor, class_names,
char_class_abbrevs, weap_spec_char_class, and all other
NUM_CLASSES-sized tables updated.
- Allowed as primary class for every race except Dwarf and Minotaur.
- do_start, advance_level, parse_player_class, roll_real_abils,
and the race/class stat bonuses handle CLASS_WARLOCK.
- PAST_CLASS macro includes Warlock (gold currency cohort).
- CXN_ALIGN_PROMPT auto-forces evil alignment at creation, with a
custom prompt line (mirrors monk neutrality and drow evil).
- Class selection menu in show_char_class_menu adds a Warlock entry.
Signature skill:
- SKILL_ELDRITCH_BLAST = 700 and MAX_SKILLS bumped to 701.
- New do_eldritch_blast command in src/classes/act.warlock.c,
modelled on do_whirlwind. Beam count scales with effective level
(character level plus twice remort generation): 1/2/3/4 beams at
levels 1-14 / 15-29 / 30-44 / 45+. Per-beam damage is
dice(1 + (lvl>4), 8) + lvl/3. Costs 3 mana + 5 move. Auto-targets
via random_opponent in combat. Fails while AFF3_MUTED.
Registered as "eldritch" and "eblast" in the command table.
Spellbook (sample_lib/etc/spells.xml plus SPELL_/SKILL_ constants):
- 14 new mortal spells: Hex, Corruption, Ray of Enfeeblement,
Shadow Bolt, Bane, Drain Life, Bestow Curse, Vampiric Touch,
Hellish Rebuke, Darkness, Fear Hex, Agony, Soul Rot, Circle of
Death (IDs 162-175).
- 3 mortal pact summons: Summon Dretch (L12), Summon Barlgura (L20,
tank/protector), Summon Vrock (L30, stun screech) at IDs 176-178.
- 6 remort spells (gen 1-5): Siphon Soul, Enervation, Finger of
Death, Summon Glabrezu (gen 2 tank), Negative Energy Flood,
Summon Balor (gen 4 capstone demon) at IDs 276-281.
- 12 existing spells re-granted to Warlock: Blindness, Charm Person,
Chill Touch, Curse, Drowsy/Sleep, Energy Drain, Poison, Slow,
Undead Protection, Word Stun, Banishment, Vampiric Regeneration.
Magic engine hooks:
- 10 new mag_affects cases (Hex, Corruption, Ray of Enfeeblement,
Bane, Bestow Curse, Darkness, Fear Hex, Agony, Soul Rot,
Enervation) using existing AFF/AFF2/AFF3 bits (no new flag bits).
- 5 new mag_damage cases (Shadow Bolt, Hellish Rebuke, Circle of
Death, Finger of Death with instakill clause, Negative Energy
Flood). Mag_areas strings for the two room-scope spells.
- NEF applies Corruption DoT to survivors in the post-damage hook.
- 3 MAG_MANUAL lifesteal handlers (Drain Life, Vampiric Touch,
Siphon Soul) at the bottom of spells.c.
- Pact-summon helper perform_summon_pact modelled on Summon Legion:
skill check, load mob, scale by skill_bonus * 1.5 / 100, charm as
pet, dominance check against can_charm_more. Placeholder mob
vnums reuse the existing legion_vnums pool until dedicated demon
mobs are built in sample_lib/world.
- Soul Rot dispel-backlash: removing SPELL_SOUL_ROT from a target
fires dice(5, 10) damage at the dispeller.
- DoT tick hooks for Corruption / Agony / Soul Rot / Enervation in
mobact.c next to the existing stigmata tick.
Alignment drift:
- Warlock pact weakens when alignment wavers. warlock_align_scale
helper returns dam for evil, dam/2 for neutral, dam/4 for good.
Applied in mag_damage, Eldritch Blast, the three lifesteal
MAG_MANUAL handlers, and the four DoT tick sites. Scaling uses
current alignment at tick time so already-applied DoTs weaken as
the caster drifts.
Content and damage messages:
- sample_lib/misc/messages gains a Warlock Abilities section with
13 fight_message records for every damage-dealing spell/skill.
- warlock_hedit.txt (gitignored) is a scratch file containing
hedit-ready help entry bodies for the maintainers to paste in.
================================================================================
|
Follow-up to the Warlock class PR, tightening the new code against the
codebase's existing style.
- act.warlock.c: add the "Copyright 1998 by John Watson" header line
that every other class file has; move libxml/parser.h up with the
other system headers; add the "// <function> - <blurb>" single-line
function comment that precedes every ACMD in the peer class files.
- do_eldritch_blast: "Blast whom?" -> "Blast who?" to match the
existing "Whirlwind who?" / "Backstab who?" phrasing.
- magic.c: drop the "/* ============ Warlock ============ */" banner
comments around the mag_affects and mag_damage Warlock case blocks.
No other per-class region in these switches uses section dividers,
so the banners read as unusual.
- magic.c: add audible = true to Hellish Rebuke and Negative Energy
Flood, matching the pattern used by other noisy damage spells
(Fireball, Flame Strike, Call Lightning).
- magic.c: rephrase the SPELL_AGONY same-symbol error from two
sentences to one, matching the existing SYMBOL_OF_PAIN error
style ("Another symbol of pain already burns upon this creature.").
- magic.c: replace the multi-line pact-drift block comment with a
single // line comment for consistency with nearby inline comments.
- spells.c: drop the WARLOCK MANUAL SPELLS banner above the helper
block, and the multi-line block comment above perform_summon_pact,
in favor of a single // line comment each.
- spell_parser.c: drop the banner comment lines around the Warlock
MAG_MANUAL dispatch cases.
- sample_lib/etc/spells.xml: drop the "<!-- Warlock Class -->" section
comment; other class-grouped spells in the XML are not separated
by section headers.
Captures the real coding conventions used in the baseline so that generated contributions to this repo can be audited against the project's actual style rather than generic C norms. The rules are compiled from a survey of existing files (act.monk.c, magic.c, spells.c, etc.) and cite file:line examples in-place. The skill includes a review procedure with automated grep checks for AI tells (em dashes, -- in prose, Doxygen openers, banner comments, XML dividers, trailing whitespace on comments), plus a blacklist of patterns that do not appear anywhere in the baseline. The intended usage is: before committing or opening a PR, invoke the skill to get a blocker/style/idiom report, then apply fixes with user approval. The skill does not auto-edit.
Applies findings from the tempuscode-style skill audit against the Warlock branch: - Convert inline /* ... */ comments inside function bodies to // comments, matching the style used by act.monk.c and siblings. Six instances across act.warlock.c, magic.c, and spells.c. - Drop the redundant "victim died" comments after damage() returns non-zero in the three lifesteal ASPELL handlers; the early return is self-explanatory. - Rephrase "Your pact falters. The Abyss does not answer." into a single sentence, since baseline error strings are one sentence. - Reformat the Warlock alignment prompt in nanny.c to match the line-break shape used by the monk equivalent (split across \r\n rather than joined by double-space).
class_can_do_abilities() in spec_procs.c hard-codes which classes can use the SPELL_BIT category, gating the 'spells' command, the 'cast' command, and spell learning. The allowed list was Mage, Cleric, Knight, Ranger only. Adding Warlock to both the primary and remort-class checks so that playing a Warlock actually lets you see and cast your spells. Caught during in-game testing: a level 49 Warlock ran 'spells' and got "A warlock cannot cast spells!" despite having granted entries in spells.xml.
Two more hard-coded class lists that excluded Warlock and turned up during live playtesting. src/magic/spell_parser.c:1600 - the cast command's gate listed only Mage/Cleric/Knight/Ranger/Vampire; a Warlock attempting 'cast hex' got "You are not learned in the ways of magic." Added IS_WARLOCK(ch) to the allow list. src/misc/limits.c:147 - the mana-regen caster-bonus (2x gain) listed Mage/Cleric/Psychic/Physic/Bard. Warlocks are the newest caster class and should get the same bonus.
Summary
Adds a new playable class, the Warlock, occupying the former
CLASS_SPARE1slot. Warlocks are an evil-only fantasy caster whose identity is debuffs + damage-over-time, anchored by an at-will signature attack called Eldritch Blast.Design decisions baked into this PR:
CXN_ALIGN_PROMPTlike monk neutrality.What's in the PR
Class shell
CLASS_SPARE1renamed toCLASS_WARLOCK(enum 14);IS_SPARE1/ITEM3_REQ_SPARE1renamed to the_WARLOCKform (bit values preserved, no data migration).prac_params,race_restr,thaco_factor,class_names,char_class_abbrevs,weap_spec_char_classpopulated.do_start,advance_level,parse_player_class,roll_real_abils, and the race/class stat bonuses all handleCLASS_WARLOCK.PAST_CLASSmacro includes Warlock (gold currency).Signature skill - Eldritch Blast
SKILL_ELDRITCH_BLAST = 700,MAX_SKILLSbumped to 701.src/classes/act.warlock.cwithdo_eldritch_blast, modelled ondo_whirlwind. Beam count scales 1/2/3/4 at effective levels 1-14 / 15-29 / 30-44 / 45+. Per-beam damagedice(1 + (lvl>4), 8) + lvl/3. Costs 3 mana + 5 move. Auto-targets in combat. Fails whileAFF3_MUTED.eldritchandeblastin the command table.Spellbook (
sample_lib/etc/spells.xml)Magic-engine hooks
mag_affectscases using existing AFF/AFF2/AFF3 bits (no new flag bits needed).mag_damagecases including Finger of Death's instakill clause and NEF's post-damage Corruption seeding.mag_areasstrings for the two room-scope spells.MAG_MANUALlifesteal handlers (Drain Life, Vampiric Touch, Siphon Soul).perform_summon_pactmodelled onspell_summon_legion: skill check, mob load,skill_bonus * 1.5 / 100scaling, charm-as-pet, dominance check againstcan_charm_more. Placeholder mob vnums reuse the existinglegion_vnumspool until dedicated Dretch / Barlgura / Vrock / Glabrezu / Balor mobs are built.SPELL_SOUL_ROTfiresdice(5, 10)damage at the dispeller.mobact.cnext to the existing stigmata tick.Alignment drift
warlock_align_scale(ch, dam)helper returnsdamfor evil,dam/2for neutral,dam/4for good. Applied inmag_damage, Eldritch Blast, the three lifesteal handlers, and the four DoT tick sites. Ticks scale by current alignment at tick time, so DoTs weaken as the caster drifts.Content
sample_lib/misc/messagesgains a Warlock Abilities section with 13fight_messagerecords covering every damage-dealing spell and Eldritch Blast.hedit.Known follow-ups (content, not code)
sample_lib/world/for training.hedithelp entries (see PR comment).Test plan
./configure && makebuilds cleanly.CXN_ALIGN_PROMPTauto-sets alignment to -666 with the pact flavor line.skillslists Eldritch Blast at 25% andspellslists Magic Missile / Chill Touch;eblast <mob>fires one beam.advance 15 / 30 / 45,eblastfires 2 / 3 / 4 beams respectively.dispel magicit; dispeller takes roughly 5d10 backlash.set alignment 0; Shadow Bolt and Eldritch Blast damage drop to about half.