Skip to content

Commit

Permalink
Created a droid pet for the jedi role. This was really fun to make - …
Browse files Browse the repository at this point in the history
…it's my hope that this makes the jedi role even better and solidifies it as the 'newb barb' role for new Hack'EM players.

The droid is quite powerful, albeit slow, but will prove a very useful companion to have around. It has resistances to almost everything, regenerates, and flies, so it should be very durable. The droid does not leave a corpse, so onces it's gone - it's gone, you will want to protect it from destruction! Keep in mind its main vulnerability is shock damage. If it runs into a web - it has a tiny saw that it can cut away web traps with.

For offensive capabilities, it has a strong melee zap touch and a ranged shocking ray zap.

However, one of the main features of the droid is it's ability to automatically BUC test and property test any items it walks over. Since it's a robot - it also never hungers, and it's tameness will never expire. So you can leave it in Sokobon forever as a item processing tool, or you can level it up and bring it out into the wild. Note that since it doesn't have hands it cannot pick up items like other pets - it probably would not be very good at stealing from shops anyway since it's so slow. A good first goal for the jedi will be finding a wand of speed monster to bump up its speed.

This droid will need a bit of playtesting, but I think we have a decent start. Other ideas that could be fun are adding: oil slick spray to blind enemies, fire extinguisher, or defensive passive saw attacks, but let's start simple and build from there.
  • Loading branch information
elunna committed Oct 10, 2023
1 parent ad4ddc4 commit 2a08130
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 275 deletions.
1 change: 1 addition & 0 deletions .hackemrc
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ OPTIONS=ghoulname:Discord
OPTIONS=birdname:Polly
OPTIONS=monkeyname:Unga-Unga
OPTIONS=wolfname:Apache
OPTIONS=droidname:R2

# The nameable fruit is always vegan
# If you change this, update the MENUCOLOR below so it matches.
Expand Down
1 change: 1 addition & 0 deletions include/decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ E NEARDATA char catname[];
E NEARDATA char dogname[];
E NEARDATA char horsename[];
E NEARDATA char ghoulname[];
E NEARDATA char droidname[];
E NEARDATA char monkeyname[];
E NEARDATA char wolfname[];
E NEARDATA char pseudoname[];
Expand Down
1 change: 1 addition & 0 deletions include/monflag.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#define MS_ANT 49 /* ants */
#define MS_PIRATE 50 /* pirates */
#define MS_MEGAROAR 51 /* capable of frightful dragon roars */
#define MS_BOT 52 /* droid sounds */

#define MR_FIRE 0x00000001L /* resists fire */
#define MR_COLD 0x00000002L /* resists cold */
Expand Down
1 change: 1 addition & 0 deletions src/decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ NEARDATA char catname[PL_PSIZ] = DUMMY;
NEARDATA char horsename[PL_PSIZ] = DUMMY;
NEARDATA char wolfname[PL_PSIZ] = DUMMY;
NEARDATA char ghoulname[PL_PSIZ] = DUMMY;
NEARDATA char droidname[PL_PSIZ] = DUMMY;
NEARDATA char monkeyname[PL_PSIZ] = DUMMY;
NEARDATA char pseudoname[PL_PSIZ] = DUMMY;
NEARDATA char ratname[PL_PSIZ] = DUMMY;
Expand Down
9 changes: 7 additions & 2 deletions src/dog.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ makedog()
petname = pseudoname;
else if (pettype == PM_GHOUL)
petname = ghoulname;
else if (pettype == PM_DROID)
petname = droidname;
else if (pettype == PM_PARROT)
petname = birdname;
else if (pettype == PM_MONKEY)
Expand Down Expand Up @@ -689,8 +691,11 @@ long nmv; /* number of moves */
else
mtmp->mspec_used -= imv;

/* reduce tameness for every 150 moves you are separated */
if (mtmp->mtame) {
/* reduce tameness for every 150 moves you are separated
* The droid never loses tameness because it cannot be
* revived.
* */
if (mtmp->mtame && mtmp->data != &mons[PM_DROID]) {
int wilder = (imv + 75) / 150;
if (mtmp->mtame > wilder)
mtmp->mtame -= wilder; /* less tame */
Expand Down
18 changes: 16 additions & 2 deletions src/dogmove.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ int maxdist;
if ((!targ->minvis || mon_prop(mtmp, SEE_INVIS))
&& !targ->mundetected)
break;
/* If the pet can't see it, it assumes it aint there */
/* If the pet can't see it, it assumes it ain't there */
targ = 0;
}
}
Expand Down Expand Up @@ -1773,7 +1773,21 @@ int after; /* this is extra fast monster movement */
wasseen = canseemon(mtmp);
remove_monster(omx, omy);
place_monster(mtmp, nix, niy);
if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {

struct obj *floor_obj;
struct obj *obj2;

if (mtmp->data == &mons[PM_DROID]) {
/* Scan all the items at the location */
for (floor_obj = level.objects[mtmp->mx][mtmp->my];
floor_obj; floor_obj = obj2) {
obj2 = floor_obj->nexthere;
/* Reveal BUC */
set_bknown(floor_obj, 1);
/* Reveal properties */
floor_obj->oprops_known |= floor_obj->oprops;
}
} else if (cursemsg[chi] && (wasseen || canseemon(mtmp))) {
/* describe top item of pile, not necessarily cursed item itself;
don't use glyph_at() here--it would return the pet but we want
to know whether an object is remembered at this map location */
Expand Down
2 changes: 2 additions & 0 deletions src/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -2600,6 +2600,8 @@ char *origbuf;
(void) strncpy(ratname, bufp, PL_PSIZ - 1);
} else if (match_varname(buf, "GHOULNAME", 3)) {
(void) strncpy(ghoulname, bufp, PL_PSIZ - 1);
} else if (match_varname(buf, "DROIDNAME", 3)) {
(void) strncpy(droidname, bufp, PL_PSIZ - 1);
} else if (match_varname(buf, "MONKEYNAME", 3)) {
(void) strncpy(monkeyname, bufp, PL_PSIZ - 1);
} else if (match_varname(buf, "BIRDNAME", 3)) {
Expand Down
13 changes: 4 additions & 9 deletions src/makemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -4293,23 +4293,18 @@ int type;
{
switch (type) {
case PM_STRAW_GOLEM:
return 20;
case PM_PAPER_GOLEM:
case PM_DROID:
return 20;
case PM_WAX_GOLEM:
return 40;
case PM_PLASTIC_GOLEM:
return 40;
case PM_ROPE_GOLEM:
return 30;
case PM_WAX_GOLEM:
case PM_PLASTIC_GOLEM:
case PM_LEATHER_GOLEM:
return 40;
case PM_GOLD_GOLEM:
return 40;
case PM_WOOD_GOLEM:
return 50;
case PM_FLESH_GOLEM:
return 40;
case PM_WOOD_GOLEM:
case PM_CLAY_GOLEM:
return 50;
case PM_STONE_GOLEM:
Expand Down
4 changes: 4 additions & 0 deletions src/mcastu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,10 @@ struct attack *mattk;
if (mdef->mhp <= 0)
return 0;

/* Currently the droid's ranged attack - not melee. */
if (mattk->adtyp == AD_ELEC)
return 0;

if ((mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) && ml) {
int cnt = 40;

Expand Down
12 changes: 12 additions & 0 deletions src/monst.c
Original file line number Diff line number Diff line change
Expand Up @@ -5798,6 +5798,18 @@ struct permonst _mons2[] = {
/*
* golems
*/
MON("droid", S_GOLEM,
LVL(3, 4, 0, 30, 0), (G_GENO | G_NOCORPSE | G_NOGEN),
A(ATTK(AT_TUCH, AD_ELEC, 3, 4),
ATTK(AT_MAGC, AD_ELEC, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1000, 1000, MS_SILENT, MZ_MEDIUM),
MR_FIRE | MR_COLD | MR_SLEEP | MR_POISON | MR_STONE
| MR_PSYCHIC | MR_SONIC | MR_DRAIN | MR_SICK, 0,
M1_FLY | M1_BREATHLESS | M1_MINDLESS | M1_NOLIMBS
| M1_NOHANDS | M1_NOTAKE | M1_REGEN,
M2_STRONG | M2_NEUTER | M2_NOPOLY,
M3_INFRAVISION, 0, 0, 10, CLR_BLUE),
MON("straw golem", S_GOLEM,
LVL(3, 12, 10, 0, 0), (G_NOHELL | G_NOCORPSE | 1),
A(ATTK(AT_CLAW, AD_PHYS, 1, 2),
Expand Down
20 changes: 20 additions & 0 deletions src/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ static struct Comp_Opt {
PL_PSIZ, DISP_IN_GAME },
{ "ghoulname", "the name of your (first) ghoul (e.g., ghoulname:Casper)",
PL_PSIZ, DISP_IN_GAME },
{ "droidname", "the name of your droid (e.g., droidname:ZL21)",
PL_PSIZ, DISP_IN_GAME },
{ "birdname", "the name of your (first) bird (e.g., birdname:Squawks)",
PL_PSIZ, DISP_IN_GAME },
{ "monkeyname", "the name of your (first) monkey (e.g., monkeyname:Ugga-Ugga)",
Expand Down Expand Up @@ -2362,6 +2364,22 @@ boolean tinitial, tfrom_file;
sanitize_name(ghoulname);
return retval;
}

fullname = "droidname";
if (match_optname(opts, fullname, 3, TRUE)) {
if (duplicate)
complain_about_duplicate(opts, 1);
if (negated) {
bad_negation(fullname, FALSE);
return FALSE;
} else if ((op = string_for_env_opt(fullname, opts, FALSE))
!= empty_optstr) {
nmcpy(droidname, op, PL_PSIZ);
} else
return FALSE;
sanitize_name(droidname);
return retval;
}

fullname = "birdname";
if (match_optname(opts, fullname, 3, TRUE)) {
Expand Down Expand Up @@ -5997,6 +6015,8 @@ char *buf;
Sprintf(buf, "%s", horsename[0] ? horsename : none);
else if (!strcmp(optname, "ghoulname"))
Sprintf(buf, "%s", ghoulname[0] ? ghoulname : none);
else if (!strcmp(optname, "droidname"))
Sprintf(buf, "%s", droidname[0] ? droidname : none);
else if (!strcmp(optname, "birdname"))
Sprintf(buf, "%s", birdname[0] ? birdname : none);
else if (!strcmp(optname, "monkeyname"))
Expand Down
2 changes: 1 addition & 1 deletion src/role.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ const struct Role roles[] = {
"the Outer Rim",
PM_JEDI,
NON_PM,
PM_LITTLE_DOG,
PM_DROID,
PM_JEDI_MASTER,
PM_PADAWAN,
PM_LORD_SIDIOUS,
Expand Down
3 changes: 3 additions & 0 deletions src/sounds.c
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,9 @@ register struct monst *mtmp;
pline_msg =
"tells you their aspirations to become great Jedi.";
break;
case MS_BOT:
pline_msg = "beep boops.";
break;
default:
pline_msg = "discusses dungeon exploration.";
break;
Expand Down
17 changes: 13 additions & 4 deletions src/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,12 +989,12 @@ struct trap *trap;
{
boolean isyou = (mtmp == &youmonst);
struct permonst *mptr = mtmp->data;

xchar x = trap->tx;
xchar y = trap->ty;

if (amorphous(mptr) || is_whirly(mptr) || flaming(mptr)
|| unsolid(mptr) || mptr == &mons[PM_GELATINOUS_CUBE]) {
xchar x = trap->tx;
xchar y = trap->ty;


if (flaming(mptr) || acidic(mptr)) {
if (domsg) {
if (isyou)
Expand All @@ -1020,7 +1020,16 @@ struct trap *trap;
}
}
return TRUE;
} else if (mptr == &mons[PM_DROID]) {
if (domsg) {
pline("%s cuts %s spider web!", Monnam(mtmp),
a_your[trap->madeby_u]);
}
deltrap(trap);
newsym(x, y);
return TRUE;
}

return FALSE;
}

Expand Down
1 change: 1 addition & 0 deletions sys/winnt/.hackemrc.template
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ OPTIONS=symset:IBMGraphics,roguesymset:RogueEpyx
#OPTIONS=dogname:Fido,catname:Morris,fruit:guava
#OPTIONS=horsename:Silver
#OPTIONS=ghoulname:Igor
#OPTIONS=droidname:ZL21
#OPTIONS=birdname:Squawks
#OPTIONS=monkeyname:Ugga-Ugga

Expand Down
Loading

0 comments on commit 2a08130

Please sign in to comment.