Skip to content

Commit

Permalink
Differentiate the various types of giants
Browse files Browse the repository at this point in the history
Most of the giants were pretty homogeneous. Sure, they had a difficulty
scale that correlated with higher levels, hit dice, and weapons, but
they didn't actually play very differently: fire, frost, and storm
giants conveying their respective resistance when eaten was about the
extent of it.

This reworks the five true giants (hill, stone, fire, frost, and storm)
so that they play differently:
- Hill giants are the weakest type, with no special abilities. In D&D
  they are traditionally the stupid, brutish, and lowest-ranked giant;
  here this means they swap stat blocks with stone giants (except for
  alignment - hill giants are still slightly chaotic; stone are still
  slightly lawful).
- Stone giants have become slightly stronger as a result of that
  statblock swap, but more importantly they now have the ability to
  wrest a boulder out of the ground when they don't have one already and
  creating a pit on their square. There are other criteria to avoid this
  behavior becoming overly annoying - not next to liquids, not in choke
  points, and so on.
- Fire giants get an active fire attack.
- Frost giants get an active frost attack.
- Storm giants get an active lightning attack, which is ranged and would
  make them significantly tougher if they weren't already far and away
  the highest-difficulty giant that usually appears only in the late
  game.

Other monsters in the giant humanoid class (plain giant, ettin,
minotaur, titan) aren't changed. The monster difficulty numbers aren't
changed, except for the hill giant/stone giant swap.

I additionally saved an encyclopedia entry for frost giants at some
point, so this commit takes the opportunity to add it.

Ideas that were considered but not implemented at this time:
- Passive attacks for the three elemental giants, either in addition to
  or instead of the active attacks. (Mostly out of fear that this would
  make them too tough.)
- Frost giants can walk on water via flash-freezing it into ice. (It's
  difficult to think of a way to make a counterpart for fire giants; if
  they could walk on ice to melt it, they'd just drown, and that would
  probably lead to weirdness in the Valkyrie quest).
  • Loading branch information
copperwater committed Jan 5, 2025
1 parent 131168e commit a115500
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 54 deletions.
13 changes: 13 additions & 0 deletions dat/data.base
Original file line number Diff line number Diff line change
Expand Up @@ -2038,6 +2038,18 @@ fox
away with his nose in the air, saying: "I am sure they are
sour."
[ Aesop's Fables ]
frost giant
"There!" I told Blackjack. He plunged toward the battle.
I leaped off his back and landed on the giant's head. When the
giant looked up, I slid off his face, shield-bashing his nose on
the way down.
"RAWWWR!' The giant staggered backward, blue blood trickling
from his nostrils.
I hit the pavement running. The Hyperborean breathed a cloud of
white mist, and the temperature dropped. The spot where I'd
landed was now coated with ice, and I was covered in frost like
a sugar donut.
[ The Last Olympian, by Rick Riordan ]
fruit
They say this is edible. Some adventurers have strange tastes.
*fung*
Expand Down Expand Up @@ -2190,6 +2202,7 @@ ghoul
ferocious fear the sinister; wolves recoil when they encounter
a ghoul.
[ Les Miserables, by Victor Hugo ]
~frost giant
*giant
giant humanoid
Giants have always walked the earth, though they are rare in
Expand Down
9 changes: 9 additions & 0 deletions doc/xnh-changelog-9.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,15 @@ changes:
hallucinating.
- Being life-saved while hallucinating.
- Monster drinking a potion where you can't see while hallucinating.
- Hill giants are now the weakest giant, taking over the statblock of the stone
giant (equivalent to the plain giant) with its 2d8 weapon attack.
- Stone giants are slightly stronger, taking over the statblock of the hill
giant with its 2d10 weapon attack. They are now able to rip boulders out of
the floor when they don't already have one, which creates a pit on that
square.
- Fire giants have a 2d4 fire touch attack.
- Frost giants have a 3d4 cold touch attack and their own encyclopedia entry.
- Storm giants have a 4d4 ranged lightning bolt attack.

### Architectural changes

29 changes: 15 additions & 14 deletions include/monsters.h
Original file line number Diff line number Diff line change
Expand Up @@ -1465,31 +1465,31 @@
M2_GIANT | M2_STRONG | M2_ROCKTHROW | M2_NASTY | M2_COLLECT
| M2_JEWELS,
M3_INFRAVISIBLE | M3_INFRAVISION, 8, CLR_CYAN, GIANT),
MON("stone giant", S_GIANT, LVL(6, 6, 0, 0, 2), (G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 10), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
SIZ(2250, 750, MS_BOAST, MZ_HUGE), 0, 0, M1_HUMANOID | M1_CARNIVORE,
M2_GIANT | M2_STRONG | M2_ROCKTHROW | M2_NASTY | M2_COLLECT
| M2_JEWELS,
M3_INFRAVISIBLE | M3_INFRAVISION, 8, CLR_GRAY, STONE_GIANT),
MON("hill giant", S_GIANT, LVL(8, 10, 6, 0, -2), (G_GENO | G_SGROUP | 1),
MON("hill giant", S_GIANT, LVL(6, 6, 0, 0, -2), (G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
SIZ(2200, 700, MS_BOAST, MZ_HUGE), 0, 0, M1_HUMANOID | M1_CARNIVORE,
M2_GIANT | M2_STRONG | M2_ROCKTHROW | M2_NASTY | M2_COLLECT
| M2_JEWELS,
M3_INFRAVISIBLE | M3_INFRAVISION, 10, CLR_CYAN, HILL_GIANT),
MON("fire giant", S_GIANT, LVL(9, 12, 4, 5, 2), (G_GENO | G_SGROUP | 1),
M3_INFRAVISIBLE | M3_INFRAVISION, 8, CLR_CYAN, HILL_GIANT),
MON("stone giant", S_GIANT, LVL(8, 10, 6, 0, 2), (G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 10), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
SIZ(2250, 750, MS_BOAST, MZ_HUGE), 0, 0, M1_HUMANOID | M1_CARNIVORE,
M2_GIANT | M2_STRONG | M2_ROCKTHROW | M2_NASTY | M2_COLLECT
| M2_JEWELS,
M3_INFRAVISIBLE | M3_INFRAVISION, 10, CLR_GRAY, STONE_GIANT),
MON("fire giant", S_GIANT, LVL(9, 12, 4, 5, 2), (G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 10), ATTK(AT_TUCH, AD_FIRE, 2, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2250, 750, MS_BOAST, MZ_HUGE), MR_FIRE, MR_FIRE,
M1_HUMANOID | M1_CARNIVORE, M2_GIANT | M2_STRONG | M2_ROCKTHROW
| M2_NASTY | M2_COLLECT | M2_JEWELS,
M3_INFRAVISIBLE | M3_INFRAVISION, 11, CLR_YELLOW, FIRE_GIANT),
MON("frost giant", S_GIANT, LVL(10, 12, 3, 10, -3),
(G_NOHELL | G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 12), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK,
NO_ATTK),
A(ATTK(AT_WEAP, AD_PHYS, 2, 12), ATTK(AT_TUCH, AD_COLD, 3, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2250, 750, MS_BOAST, MZ_HUGE), MR_COLD, MR_COLD,
M1_HUMANOID | M1_CARNIVORE, M2_GIANT | M2_STRONG | M2_ROCKTHROW
| M2_NASTY | M2_COLLECT | M2_JEWELS,
Expand All @@ -1502,8 +1502,9 @@
M2_HOSTILE | M2_STRONG | M2_NASTY | M2_COLLECT,
M3_INFRAVISIBLE | M3_INFRAVISION, 13, CLR_BROWN, ETTIN),
MON("storm giant", S_GIANT, LVL(16, 12, 3, 10, -3),
(G_GENO | G_SGROUP | 1), A(ATTK(AT_WEAP, AD_PHYS, 2, 12), NO_ATTK,
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
(G_GENO | G_SGROUP | 1),
A(ATTK(AT_WEAP, AD_PHYS, 2, 12), ATTK(AT_MAGC, AD_ELEC, 4, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2250, 750, MS_BOAST, MZ_HUGE), MR_ELEC, MR_ELEC,
M1_HUMANOID | M1_CARNIVORE, M2_GIANT | M2_STRONG | M2_ROCKTHROW
| M2_NASTY | M2_COLLECT | M2_JEWELS,
Expand Down
34 changes: 34 additions & 0 deletions src/monmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,40 @@ dochug(register struct monst* mtmp)
return 0;
}
}
/* stone giants can unearth new boulders */
else if (!nearby && mdat == &mons[PM_STONE_GIANT] && !mtmp->mpeaceful
&& mtmp->mspec_used < 1 && !m_carrying(mtmp, BOULDER)
&& levl[mtmp->mx][mtmp->my].typ == ROOM) {
/* this will create a pit, so they won't do it next to liquids; also
* stop them from doing it in probable choke points */
int rms_adj = 0;
boolean abort = FALSE;
coordxy x, y;
for (x = mtmp->mx - 1; x <= mtmp->mx + 1; x++) {
for (y = mtmp->my - 1; y <= mtmp->my + 1; y++) {
if (x == mtmp->mx && y == mtmp->my)
continue;
if (is_pool_or_lava(x, y))
abort = TRUE;
if (levl[x][y].typ == ROOM && !t_at(x, y))
rms_adj++;
}
}
if (!abort && rms_adj > 4) {
/* they do not fall into the pit they just made */
struct trap *ttmp = maketrap(mtmp->mx, mtmp->my, PIT);
if (canseemon(mtmp)) {
pline("%s rips a boulder out of the ground!", Monnam(mtmp));
ttmp->tseen = TRUE;
}
mongets(mtmp, BOULDER);
/* it would be silly if they can fall right back in again */
mon_learns_traps(mtmp, PIT);
/* can't rip out another boulder immediately */
mtmp->mspec_used = rnd(5) + 5;
return 0;
}
}

if (mdat == &mons[PM_JUIBLEX] && special_juiblex_actions(mtmp))
return 0;
Expand Down
80 changes: 40 additions & 40 deletions win/share/monsters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6726,45 +6726,7 @@ Z = (195, 195, 195)
.....CLJACLJAAAA
...LLLLJ.CLLLKAA
}
# tile 350 (stone giant,male)
{
......JJJJAA....
....JJJJJJJJA...
....JJLLLLJJA...
....JFFLLFFJA...
....JLLLLLLJA...
....ALLAALLAAA..
.....ALLLLJAAAA.
..CCLLJJJJLLCCAA
.CLLLCCKCKCLLLCA
.LLLAAKCKCLKLLLA
.LLPPPACCLLAALLA
.LLPPPPAKKJAALLA
.CLCPPPAJJKKCLAA
..LLPPALACLJLLAA
.....ALJACLJAAAA
...LLLLJ.CLLLKAA
}
# tile 351 (stone giant,female)
{
......JJJJAA....
....JJJJJJJJA...
....JJLLLLJJA...
....JFFLLFFJA...
....JLLLLLLJA...
....ALLAALLAAA..
.....ALLLLJAAAA.
..CCLLJJJJLLCCAA
.CLLLCCKCKCLLLCA
.LLLAAKCKCLKLLLA
.LLPPPACCLLAALLA
.LLPPPPAKKJAALLA
.CLCPPPAJJKKCLAA
..LLPPALACLJLLAA
.....ALJACLJAAAA
...LLLLJ.CLLLKAA
}
# tile 352 (hill giant,male)
# tile 350 (hill giant,male)
{
......JJJJAA....
....JJJJJJJJA...
Expand All @@ -6783,7 +6745,7 @@ Z = (195, 195, 195)
.....CLJACLJAAAA
...LLLLJ.LLLLKAA
}
# tile 353 (hill giant,female)
# tile 351 (hill giant,female)
{
......JJJJAA....
....JJJJJJJJA...
Expand All @@ -6802,6 +6764,44 @@ Z = (195, 195, 195)
.....CLJACLJAAAA
...LLLLJ.LLLLKAA
}
# tile 352 (stone giant,male)
{
......JJJJAA....
....JJJJJJJJA...
....JJLLLLJJA...
....JFFLLFFJA...
....JLLLLLLJA...
....ALLAALLAAA..
.....ALLLLJAAAA.
..CCLLJJJJLLCCAA
.CLLLCCKCKCLLLCA
.LLLAAKCKCLKLLLA
.LLPPPACCLLAALLA
.LLPPPPAKKJAALLA
.CLCPPPAJJKKCLAA
..LLPPALACLJLLAA
.....ALJACLJAAAA
...LLLLJ.CLLLKAA
}
# tile 353 (stone giant,female)
{
......JJJJAA....
....JJJJJJJJA...
....JJLLLLJJA...
....JFFLLFFJA...
....JLLLLLLJA...
....ALLAALLAAA..
.....ALLLLJAAAA.
..CCLLJJJJLLCCAA
.CLLLCCKCKCLLLCA
.LLLAAKCKCLKLLLA
.LLPPPACCLLAALLA
.LLPPPPAKKJAALLA
.CLCPPPAJJKKCLAA
..LLPPALACLJLLAA
.....ALJACLJAAAA
...LLLLJ.CLLLKAA
}
# tile 354 (fire giant,male)
{
....PPDDDDAA....
Expand Down

0 comments on commit a115500

Please sign in to comment.