Add the dwarf multicannon - #1201
Open
HarleyGilpin wants to merge 1 commit into
Open
Conversation
The four cannon parts, cannonballs, Nulodion's shop and the "cannon" hitsplat all already existed, but nothing read them - the parts were dead weight and the immune_cannon npc param had no consumer. Name cache objects 6-9 as the four build stages, register the rotation animations (514-521) and the cannonball projectile, then add a script that assembles a cannon from the parts, rotates it one octant per tick and fires a single cannonball into the wedge it faces - eight per 4.8 second revolution. Neighbouring wedges overlap, so a target sitting in an overlap is fired on twice per revolution. Targets are picked by range, line of sight, the immune_cannon param and the single-way combat rules. Line of sight is traced from a tile clear of the cannon's own 3x3 footprint and shots leave the barrel tip, since the cannon blocks its own line of sight from the centre. A hit claims an unclaimed target: hit() called from a script never emits combatStart, so the target would otherwise be left flagged under attack by nobody, and Target.attackable then rejects it as "someone else is fighting that" on every later tick. Damage is a flat roll capped at 300 with the owner's ranged accuracy, giving 2 ranged experience per 10 life points and no constitution experience, so CombatExperience gains a cannon branch that returns before the constitution grant. Cannons decay 25 minutes after being placed, warning at 20, and hand the parts back to the inventory or the bank. Logging out loses the cannon instead, recording what was owed so Nulodion replaces it free of charge, loaded with the cannonballs that were in it. Setup is refused in the areas that ban cannons, via a new no_cannon area tag with flavour tags for the locations that word the refusal differently. Nulodion gains his dialogue: a whole cannon for 750,000 coins along with the mould and instruction manual, the two routes into his parts shop, the cannon explanation, and the replacement flow.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1192.
Screencast_20260822_145934.webm
Cannon
immune_cannon(first consumer of the param) and the single-way combat rules.no_cannonarea tag plus flavour tags for the locations that word the refusal differently.Nulodion
Sells a whole cannon for 750,000 coins along with the mould and instruction manual, both routes into the parts shop, the cannon explanation, and replaces a cannon lost on logout — loaded with the cannonballs that were in it.
Notes
Two things needed working around, both commented at the call site:
hit()called from a script never emitscombatStart, so the target is left flagged under attack with no attacker, andTarget.attackablethen rejects it as "someone else is fighting that" on every later tick, the cannon would fire at a monster once and ignore it for ~8 ticks. It now claims an unclaimed target after hitting it. This is scoped to the cannon; the underlying behaviour affects any script callinghit()directly and is probably worth fixing at the root separately.32 tests - All tests passed.