summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-06-27 09:58:49 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2009-06-27 09:58:49 +0000
commit7aa3305f41d2f073710d9a732bd29572b704bc49 (patch)
tree374aa17118ecb68bc4c237176506dbaf9aafb0b7
parent3cc681e30ac236f7b88adece29f194cb30138ec8 (diff)
downloadcrawl-ref-7aa3305f41d2f073710d9a732bd29572b704bc49.tar.gz
crawl-ref-7aa3305f41d2f073710d9a732bd29572b704bc49.zip
* Moved most hard-coded non-standard unrandart behaviour to art-func.h,
specifically code for equipping, unequpping, an equipped unrandart doing something every time world_reacts() is called (special wield effects), melee hit effects, and evoking. Left hardcoded outside of art-func.h: * Sword of Cerebov temproarily downgrading the defender's fire resistance. * Staff of Olgreb boosting poison spells, as if it were a staff of poison. * Vampire's Tooth always getting maximal vampiric drain. * Mace of Variablity's initial pluses being chosen at creation time. * Since what used to be special wield effects is now handled very differently, noisy weapons and the lantern of shadows effects are handled with player attributes rather than SPWLD_NOISES and SPWLD_SHADOW. * Unrandarts can now have an elemental colour for their colour (currently only used for the Mace of Variability). * Unrandarts' value modification, being special, and being evil are now handled in art-data.txt rather than being hardcoded. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10055 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r--crawl-ref/source/acr.cc10
-rw-r--r--crawl-ref/source/art-data.h312
-rw-r--r--crawl-ref/source/art-data.txt55
-rw-r--r--crawl-ref/source/art-func.h484
-rw-r--r--crawl-ref/source/artefact.cc28
-rw-r--r--crawl-ref/source/artefact.h35
-rw-r--r--crawl-ref/source/debug.cc23
-rw-r--r--crawl-ref/source/delay.cc2
-rw-r--r--crawl-ref/source/effects.cc2
-rw-r--r--crawl-ref/source/fight.cc75
-rw-r--r--crawl-ref/source/fight.h8
-rw-r--r--crawl-ref/source/invent.cc38
-rw-r--r--crawl-ref/source/it_use2.cc57
-rw-r--r--crawl-ref/source/it_use2.h2
-rw-r--r--crawl-ref/source/it_use3.cc394
-rw-r--r--crawl-ref/source/it_use3.h5
-rw-r--r--crawl-ref/source/item_use.cc160
-rw-r--r--crawl-ref/source/item_use.h6
-rw-r--r--crawl-ref/source/itemprop.h17
-rw-r--r--crawl-ref/source/makefile.mgw5
-rw-r--r--crawl-ref/source/makefile.unix5
-rw-r--r--crawl-ref/source/makefile_tiles.mgw5
-rw-r--r--crawl-ref/source/makefile_tiles.unix5
-rw-r--r--crawl-ref/source/player.cc10
-rw-r--r--crawl-ref/source/religion.cc31
-rw-r--r--crawl-ref/source/shopping.cc53
-rwxr-xr-xcrawl-ref/source/util/art-data.pl224
-rw-r--r--crawl-ref/source/view.cc4
28 files changed, 1281 insertions, 774 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 97636e3113..a16226327e 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2582,8 +2582,14 @@ void world_reacts()
mprf(MSGCH_DIAGNOSTICS, "stealth: %d", stealth );
#endif
- if (you.unrand_reacts != SPWLD_NONE)
- special_wielded();
+ if (you.attribute[ATTR_NOISES])
+ noisy_equipment();
+
+ if (you.attribute[ATTR_SHADOWS])
+ shadow_lantern_effect();
+
+ if (you.unrand_reacts != 0)
+ unrand_reacts();
if (!crawl_state.arena && one_chance_in(10))
{
diff --git a/crawl-ref/source/art-data.h b/crawl-ref/source/art-data.h
index c25124fef0..06a0e26b99 100644
--- a/crawl-ref/source/art-data.h
+++ b/crawl-ref/source/art-data.h
@@ -20,12 +20,17 @@
#error "art-data.h included twice!"
#endif
+#ifndef ART_FUNC_H
+#error "art-func.h must be included before art-data.h"
+#endif
+
#define ART_DATA_H
/* 1: UNRAND_DUMMY1 */
{
"DUMMY UNRANDART 1", "DUMMY UNRANDART 1",
- OBJ_UNASSIGNED, 250, 250, 250, BLACK,
+ OBJ_UNASSIGNED, 250, 250, 250, BLACK, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -37,29 +42,33 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 2: UNRAND_SINGING_SWORD */
{
"Singing Sword", "golden long sword",
- OBJ_WEAPONS, WPN_LONG_SWORD, +7, +7, YELLOW,
+ OBJ_WEAPONS, WPN_LONG_SWORD, +7, +7, YELLOW, 1200,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0,
},
"",
"This blessed weapon loves nothing more than to sing to its owner, whether they want it to or not.",
"",
+ _SINGING_SWORD_equip, _SINGING_SWORD_unequip, NULL, NULL, NULL,
},
/* 3: UNRAND_TROG */
{
"Wrath of Trog", "bloodstained battleaxe",
- OBJ_WEAPONS, WPN_BATTLEAXE, +3, +11, RED,
+ OBJ_WEAPONS, WPN_BATTLEAXE, +3, +11, RED, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -71,12 +80,14 @@
"",
"This was the favourite weapon of the old god Trog, before it was lost one day. It induces a bloodthirsty berserker rage in anyone who uses it to strike another.",
"",
+ _TROG_equip, _TROG_unequip, NULL, _TROG_melee_effect, NULL,
},
/* 4: UNRAND_VARIABILITY */
{
"Mace of Variability", "shimmering mace",
- OBJ_WEAPONS, WPN_MACE, 0, 0, BLACK,
+ OBJ_WEAPONS, WPN_MACE, 0, 0, ETC_RANDOM, 700,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -88,12 +99,14 @@
"",
"It is rather unreliable.",
"",
+ NULL, NULL, _VARIABILITY_world_reacts, NULL, NULL,
},
/* 5: UNRAND_PRUNE */
{
"Glaive of Prune", "purple glaive",
- OBJ_WEAPONS, WPN_GLAIVE, 0, +12, MAGENTA,
+ OBJ_WEAPONS, WPN_GLAIVE, 0, +12, MAGENTA, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -105,12 +118,14 @@
"",
"It is the creation of a mad god, and carries a curse which transforms anyone possessing it into a prune. Fortunately, the curse works very slowly, and one can use it briefly with no consequences worse than slightly purple skin and a few wrinkles.",
"",
+ _PRUNE_equip, NULL, NULL, NULL, NULL,
},
/* 6: UNRAND_POWER */
{
"Sword of Power", "chunky great sword",
- OBJ_WEAPONS, WPN_GREAT_SWORD, 0, 0, RED,
+ OBJ_WEAPONS, WPN_GREAT_SWORD, 0, 0, RED, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -122,12 +137,14 @@
"",
"It rewards the powerful with power and the meek with weakness.",
"",
+ _POWER_equip, NULL, _POWER_world_reacts, NULL, NULL,
},
/* 7: UNRAND_OLGREB */
{
"Staff of Olgreb", "green glowing staff",
- OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, GREEN,
+ OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, GREEN, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_VENOM, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0,
@@ -139,12 +156,14 @@
"",
"It was the magical weapon wielded by the mighty wizard Olgreb before he met his fate somewhere within these dungeons. It increases the ability of its wielder to use venomous magic, and carries magical powers which can be evoked.",
"",
+ _OLGREB_equip, _OLGREB_unequip, _OLGREB_world_reacts, NULL, _OLGREB_evoke,
},
/* 8: UNRAND_WUCAD_MU */
{
"Staff of Wucad Mu", "ephemeral quarterstaff",
- OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, BROWN,
+ OBJ_WEAPONS, WPN_QUARTERSTAFF, 0, 0, BROWN, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -156,12 +175,14 @@
"",
"Its power varies in proportion to its wielder's intelligence. Using it can be a bit risky.",
"",
+ _WUCAD_MU_equip, _WUCAD_MU_unequip, _WUCAD_MU_world_reacts, _WUCAD_MU_melee_effect, _WUCAD_MU_evoke,
},
/* 9: UNRAND_VAMPIRES_TOOTH */
{
"Vampire's Tooth", "ivory dagger",
- OBJ_WEAPONS, WPN_DAGGER, +3, +4, WHITE,
+ OBJ_WEAPONS, WPN_DAGGER, +3, +4, WHITE, 1000,
+ UNRAND_FLAG_SPECIAL,
{
SPWPN_VAMPIRICISM, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -173,29 +194,33 @@
"",
"It is lethally vampiric.",
"",
+ _VAMPIRES_TOOTH_equip, NULL, NULL, NULL, NULL,
},
/* 10: UNRAND_CURSES */
{
"Scythe of Curses", "warped scythe",
- OBJ_WEAPONS, WPN_SCYTHE, +13, +13, DARKGREY,
+ OBJ_WEAPONS, WPN_SCYTHE, +13, +13, DARKGREY, 800,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
- -1, 0, 0,
+ 3, 0, 0,
},
"",
"This weapon carries a terrible and highly irritating curse.",
"",
+ _CURSES_equip, NULL, _CURSES_world_reacts, _CURSES_melee_effect, NULL,
},
/* 11: UNRAND_TORMENT */
{
"Sceptre of Torment", "jewelled golden mace",
- OBJ_WEAPONS, WPN_MACE, +7, +6, YELLOW,
+ OBJ_WEAPONS, WPN_MACE, +7, +6, YELLOW, 1200,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -207,12 +232,14 @@
"",
"This truly accursed weapon is an instrument of Hell.",
"",
+ _TORMENT_equip, NULL, _TORMENT_world_reacts, _TORMENT_melee_effect, NULL,
},
/* 12: UNRAND_ZONGULDROK */
{
"Sword of Zonguldrok", "bone long sword",
- OBJ_WEAPONS, WPN_LONG_SWORD, +9, +9, LIGHTGREY,
+ OBJ_WEAPONS, WPN_LONG_SWORD, +9, +9, LIGHTGREY, 1250,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -224,12 +251,14 @@
"",
"This dreadful weapon is used at the user's peril.",
"",
+ _ZONGULDROK_equip, NULL, _ZONGULDROK_world_reacts, _ZONGULDROK_melee_effect, NULL,
},
/* 13: UNRAND_CEREBOV */
{
"Sword of Cerebov", "great serpentine sword",
- OBJ_WEAPONS, WPN_GREAT_SWORD, +6, +6, YELLOW,
+ OBJ_WEAPONS, WPN_GREAT_SWORD, +6, +6, YELLOW, 2000,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_FLAMING, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -241,12 +270,14 @@
"Eerie flames cover its twisted blade.",
"",
"",
+ NULL, NULL, NULL, _CEREBOV_melee_effect, NULL,
},
/* 14: UNRAND_DISPATER */
{
"Staff of Dispater", "golden staff",
- OBJ_WEAPONS, WPN_QUARTERSTAFF, +4, +4, YELLOW,
+ OBJ_WEAPONS, WPN_QUARTERSTAFF, +4, +4, YELLOW, 1200,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -258,12 +289,14 @@
"",
"This legendary item can unleash the fury of Hell.",
"",
+ NULL, NULL, NULL, _DISPATER_melee_effect, _DISPATER_evoke,
},
/* 15: UNRAND_ASMODEUS */
{
"Sceptre of Asmodeus", "ruby sceptre",
- OBJ_WEAPONS, WPN_QUARTERSTAFF, +7, +7, RED,
+ OBJ_WEAPONS, WPN_QUARTERSTAFF, +7, +7, RED, 1500,
+ UNRAND_FLAG_SPECIAL | UNRAND_FLAG_EVIL,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -275,12 +308,14 @@
"",
"It carries some of the powers of the arch-fiend Asmodeus.",
"",
+ NULL, NULL, NULL, _ASMODEUS_melee_effect, _ASMODEUS_evoke,
},
/* 16: UNRAND_BLOODBANE */
{
"long sword \"Bloodbane\"", "blackened long sword",
- OBJ_WEAPONS, WPN_LONG_SWORD, +7, +8, DARKGREY,
+ OBJ_WEAPONS, WPN_LONG_SWORD, +7, +8, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VORPAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -292,12 +327,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 17: UNRAND_FLAMING_DEATH */
{
"scimitar of Flaming Death", "smoking scimitar",
- OBJ_WEAPONS, WPN_SCIMITAR, +7, +5, RED,
+ OBJ_WEAPONS, WPN_SCIMITAR, +7, +5, RED, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_FLAMING, 0, 0, 0, 0, 0,
2, -1, 0, 1, 0, 20,
@@ -309,12 +346,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 18: UNRAND_BRILLIANCE */
{
"mace of Brilliance", "brightly glowing mace",
- OBJ_WEAPONS, WPN_MACE, +5, +5, WHITE,
+ OBJ_WEAPONS, WPN_MACE, +5, +5, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_HOLY_WRATH, 5, 0, 0, 5, 0,
0, 0, 0, 0, 1, 0,
@@ -326,12 +365,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 19: UNRAND_LEECH */
{
"demon blade \"Leech\"", "runed demon blade",
- OBJ_WEAPONS, WPN_DEMON_BLADE, +13, +4, MAGENTA,
+ OBJ_WEAPONS, WPN_DEMON_BLADE, +13, +4, MAGENTA, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VAMPIRICISM, 0, -1, -1, -1, -1,
0, 0, 0, 0, 1, 0,
@@ -343,12 +384,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 20: UNRAND_CHILLY_DEATH */
{
"dagger of Chilly Death", "sapphire dagger",
- OBJ_WEAPONS, WPN_DAGGER, +5, +7, LIGHTBLUE,
+ OBJ_WEAPONS, WPN_DAGGER, +5, +7, LIGHTBLUE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_FREEZING, 0, 0, 0, 0, 0,
-1, 2, 0, 1, 0, 20,
@@ -360,12 +403,14 @@
"A dagger made of one huge piece of sapphire.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 21: UNRAND_MORG */
{
"dagger \"Morg\"", "rusty dagger",
- OBJ_WEAPONS, WPN_DAGGER, -1, +4, LIGHTRED,
+ OBJ_WEAPONS, WPN_DAGGER, -1, +4, LIGHTRED, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_PAIN, 0, 0, 0, 5, 0,
0, 0, 0, 0, 0, 30,
@@ -377,12 +422,14 @@
"An ugly rusty dagger.",
"",
"Many years ago it was the property of a powerful mage called Boris. He got lost in the Dungeon while seeking the Orb.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 22: UNRAND_FINISHER */
{
"scythe \"Finisher\"", "blackened scythe",
- OBJ_WEAPONS, WPN_SCYTHE, +3, +5, DARKGREY,
+ OBJ_WEAPONS, WPN_SCYTHE, +3, +5, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_SPEED, 0, 0, 3, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -394,12 +441,14 @@
"A long and sharp scythe, specially modified for combat purposes.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 23: UNRAND_PUNK */
{
"sling \"Punk\"", "blue sling",
- OBJ_WEAPONS, WPN_SLING, +9, +12, LIGHTBLUE,
+ OBJ_WEAPONS, WPN_SLING, +9, +12, LIGHTBLUE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_FROST, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0,
@@ -411,12 +460,14 @@
"A sling made of weird blue leather.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 24: UNRAND_KRISHNA */
{
"bow of Krishna \"Sharnga\"", "golden bow",
- OBJ_WEAPONS, WPN_BOW, +8, +8, YELLOW,
+ OBJ_WEAPONS, WPN_BOW, +8, +8, YELLOW, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_SPEED, 0, 0, 0, 0, 3,
0, 0, 0, 0, 0, 0,
@@ -428,12 +479,14 @@
"A wonderful golden bow.",
"",
"It once belonged to a foreign god. It works best with special arrows which are not generally available.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 25: UNRAND_SKULLCRUSHER */
{
"giant club \"Skullcrusher\"", "brutal giant club",
- OBJ_WEAPONS, WPN_GIANT_CLUB, +0, +5, BROWN,
+ OBJ_WEAPONS, WPN_GIANT_CLUB, +0, +5, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_SPEED, 0, 0, 5, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -445,12 +498,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 26: UNRAND_GUARD */
{
"glaive of the Guard", "polished glaive",
- OBJ_WEAPONS, WPN_GLAIVE, +5, +8, LIGHTCYAN,
+ OBJ_WEAPONS, WPN_GLAIVE, +5, +8, LIGHTCYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_ELECTROCUTION, 5, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -462,12 +517,14 @@
"",
"",
"This weapon once belonged to Gar Dogh, the guard of a king's treasures. According to legend he was lost somewhere in the Dungeon.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 27: UNRAND_JIHAD */
{
"sword of Jihad", "crystal sword",
- OBJ_WEAPONS, WPN_LONG_SWORD, +12, +10, WHITE,
+ OBJ_WEAPONS, WPN_LONG_SWORD, +12, +10, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_HOLY_WRATH, 0, 3, 0, 0, 0,
0, 0, 0, 0, 1, 20,
@@ -479,12 +536,14 @@
"A long sword made of one huge piece of crystal.",
"",
"This sword was The Shining One's gift to a worshipper.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 28: UNRAND_HELLFIRE */
{
"crossbow \"Hellfire\"", "flaming crossbow",
- OBJ_WEAPONS, WPN_CROSSBOW, +6, +9, LIGHTRED,
+ OBJ_WEAPONS, WPN_CROSSBOW, +6, +9, LIGHTRED, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_FLAME, 0, 0, 0, 0, 0,
2, -1, 0, 0, 0, 40,
@@ -496,12 +555,14 @@
"A flaming crossbow, forged in the fires of the Hells.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 29: UNRAND_DOOM_KNIGHT */
{
"sword of the Doom Knight", "adamantine great sword",
- OBJ_WEAPONS, WPN_GREAT_SWORD, +13, +13, BLUE,
+ OBJ_WEAPONS, WPN_GREAT_SWORD, +13, +13, BLUE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_PAIN, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 50,
@@ -513,12 +574,14 @@
"An adamantine great sword.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 30: UNRAND_EOS */
{
"\"Eos\"", "encrusted morningstar",
- OBJ_WEAPONS, WPN_MORNINGSTAR, +5, +5, LIGHTCYAN,
+ OBJ_WEAPONS, WPN_MORNINGSTAR, +5, +5, LIGHTCYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_ELECTROCUTION, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
@@ -530,12 +593,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 31: UNRAND_BOTONO */
{
"spear of the Botono", "ebony spear",
- OBJ_WEAPONS, WPN_SPEAR, +2, +10, DARKGREY,
+ OBJ_WEAPONS, WPN_SPEAR, +2, +10, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VAMPIRICISM, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0,
@@ -547,12 +612,14 @@
"",
"",
"A really dark and malign artefact, which no wise man would even touch.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 32: UNRAND_OCTOPUS_KING */
{
"trident of the Octopus King", "mangy trident",
- OBJ_WEAPONS, WPN_TRIDENT, +10, +4, CYAN,
+ OBJ_WEAPONS, WPN_TRIDENT, +10, +4, CYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VENOM, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 50,
@@ -564,12 +631,14 @@
"",
"",
"This trident was stolen many years ago from the Octopus King's garden by a really unimportant and already dead man. But beware of the Octopus King's wrath!",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 33: UNRAND_ARGA */
{
"mithril axe \"Arga\"", "mithril axe",
- OBJ_WEAPONS, WPN_WAR_AXE, +10, +6, WHITE,
+ OBJ_WEAPONS, WPN_WAR_AXE, +10, +6, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_SPEED, 0, 0, 2, 0, 0,
0, 0, 0, 0, 0, 30,
@@ -581,12 +650,14 @@
"A beautiful mithril axe, probably lost by some dwarven hero.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 34: UNRAND_ELEMENTAL_STAFF */
{
"Elemental Staff", "black staff",
- OBJ_WEAPONS, WPN_QUARTERSTAFF, +3, +1, DARKGREY,
+ OBJ_WEAPONS, WPN_QUARTERSTAFF, +3, +1, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_PROTECTION, 0, 0, 0, 0, 0,
2, 2, 0, 0, 0, 60,
@@ -598,12 +669,14 @@
"",
"",
"This powerful staff used to belong to the leader of the Guild of Five Elements.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 35: UNRAND_SNIPER */
{
"hand crossbow \"Sniper\"", "black crossbow",
- OBJ_WEAPONS, WPN_HAND_CROSSBOW, +10, +0, DARKGREY,
+ OBJ_WEAPONS, WPN_HAND_CROSSBOW, +10, +0, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VENOM, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -615,12 +688,14 @@
"A hand crossbow made of some black material.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 36: UNRAND_PIERCER */
{
"longbow \"Piercer\"", "very long metal bow",
- OBJ_WEAPONS, WPN_LONGBOW, +2, +10, CYAN,
+ OBJ_WEAPONS, WPN_LONGBOW, +2, +10, CYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VORPAL, 0, -2, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -632,12 +707,14 @@
"An exceptionally large metal longbow.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 37: UNRAND_BLOWGUN_ASSASSIN */
{
"blowgun of the Assassin", "tiny blowgun",
- OBJ_WEAPONS, WPN_BLOWGUN, +6, +6, WHITE,
+ OBJ_WEAPONS, WPN_BLOWGUN, +6, +6, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -649,12 +726,14 @@
"It is designed for easy concealment, but still packs a nasty punch.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 38: UNRAND_WYRMBANE */
{
"Wyrmbane", "scale-covered lance",
- OBJ_WEAPONS, WPN_SPEAR, +9, +6, LIGHTGREEN,
+ OBJ_WEAPONS, WPN_SPEAR, +9, +6, LIGHTGREEN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_DRAGON_SLAYING, 5, 0, 0, 0, 0,
1, 0, 0, 1, 0, 0,
@@ -666,12 +745,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 39: UNRAND_SPRIGGANS_KNIFE */
{
"Spriggan's Knife", "dainty little knife",
- OBJ_WEAPONS, WPN_KNIFE, +4, +10, LIGHTCYAN,
+ OBJ_WEAPONS, WPN_KNIFE, +4, +10, LIGHTCYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_NORMAL, 0, 4, 0, 0, 4,
0, 0, 0, 0, 0, 20,
@@ -683,12 +764,14 @@
"A dainty little knife.",
"",
"This knife was made by Spriggans, or for Spriggans, or possibly from Spriggans. Anyway, it's in some way associated with those fey folk.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 40: UNRAND_PLUTONIUM_SWORD */
{
"plutonium sword", "glowing long sword",
- OBJ_WEAPONS, WPN_LONG_SWORD, +12, +16, LIGHTGREEN,
+ OBJ_WEAPONS, WPN_LONG_SWORD, +12, +16, LIGHTGREEN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -700,12 +783,14 @@
"A long sword made of weird glowing metal.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 41: UNRAND_UNDEADHUNTER */
{
"great mace \"Undeadhunter\"", "great steel mace",
- OBJ_WEAPONS, WPN_GREAT_MACE, +7, +7, LIGHTGREY,
+ OBJ_WEAPONS, WPN_GREAT_MACE, +7, +7, LIGHTGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_HOLY_WRATH, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0,
@@ -717,12 +802,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 42: UNRAND_SERPENT_SCOURGE */
{
"whip \"Serpent-Scourge\"", "forked whip",
- OBJ_WEAPONS, WPN_WHIP, +5, +10, DARKGREY,
+ OBJ_WEAPONS, WPN_WHIP, +5, +10, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_VENOM, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0,
@@ -734,12 +821,14 @@
"",
"A double-ended whip made from the cured hides of the Lair of Beasts' deadly grey snakes.",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 43: UNRAND_ACCURACY */
{
"knife of Accuracy", "thin dagger",
- OBJ_WEAPONS, WPN_DAGGER, +27, -1, LIGHTCYAN,
+ OBJ_WEAPONS, WPN_DAGGER, +27, -1, LIGHTCYAN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -751,12 +840,14 @@
"",
"",
"It is almost unerringly accurate.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 44: UNRAND_CRYSTAL_SPEAR */
{
"Lehudib's crystal spear", "crystal spear",
- OBJ_WEAPONS, WPN_SPEAR, +6, +6, GREEN,
+ OBJ_WEAPONS, WPN_SPEAR, +6, +6, GREEN, 0,
+ UNRAND_FLAG_NONE,
{
SPWPN_NORMAL, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
@@ -768,12 +859,14 @@
"",
"",
"Presumably this relic led to the invention of the famous spell, or maybe the other way around.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 45: UNRAND_IGNORANCE */
{
"shield of Ignorance", "dull large shield",
- OBJ_ARMOUR, ARM_LARGE_SHIELD, +5, 0, BROWN,
+ OBJ_ARMOUR, ARM_LARGE_SHIELD, +5, 0, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 2, 2, 0, -6, 0,
0, 0, 0, 0, 1, 0,
@@ -785,12 +878,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 46: UNRAND_AUGMENTATION */
{
"robe of Augmentation", "silk robe",
- OBJ_ARMOUR, ARM_ROBE, +4, 0, LIGHTRED,
+ OBJ_ARMOUR, ARM_ROBE, +4, 0, LIGHTRED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 2, 2, 2,
0, 0, 0, 0, 0, 0,
@@ -802,12 +897,14 @@
"A robe made of the finest silk.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 47: UNRAND_THIEF */
{
"cloak of the Thief", "tattered cloak",
- OBJ_ARMOUR, ARM_CLOAK, +1, 0, DARKGREY,
+ OBJ_ARMOUR, ARM_CLOAK, +1, 0, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 2, 0, 0, 2,
0, 0, 0, 0, 0, 0,
@@ -819,12 +916,14 @@
"",
"",
"It allows its wearer to excel in the arts of thievery.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 48: UNRAND_BULLSEYE */
{
"shield \"Bullseye\"", "round shield",
- OBJ_ARMOUR, ARM_SHIELD, +10, 0, RED,
+ OBJ_ARMOUR, ARM_SHIELD, +10, 0, RED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, -5, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -836,12 +935,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 49: UNRAND_DYROVEPREVA */
{
"crown of Dyrovepreva", "jewelled bronze crown",
- OBJ_ARMOUR, ARM_CAP, +3, 0, BROWN,
+ OBJ_ARMOUR, ARM_CAP, +3, 0, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 2, 0,
0, 0, 1, 0, 0, 0,
@@ -853,12 +954,14 @@
"A large crown of dull bronze, set with a dazzling array of gemstones.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 50: UNRAND_MISFORTUNE */
{
"robe of Misfortune", "fabulously ornate robe",
- OBJ_ARMOUR, ARM_ROBE, -5, 0, MAGENTA,
+ OBJ_ARMOUR, ARM_ROBE, -5, 0, MAGENTA, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, -4, -2, -2, -2,
0, 0, 0, 0, 0, 0,
@@ -870,12 +973,14 @@
"A splendid flowing robe of fur and silk.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 51: UNRAND_FLASH */
{
"cloak of Flash", "vibrating cloak",
- OBJ_ARMOUR, ARM_CLOAK, +3, 0, RED,
+ OBJ_ARMOUR, ARM_CLOAK, +3, 0, RED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -887,12 +992,14 @@
"A vibrating cloak.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 52: UNRAND_BOOTS_ASSASSIN */
{
"boots of the Assassin", "soft boots",
- OBJ_ARMOUR, ARM_BOOTS, +2, 0, BROWN,
+ OBJ_ARMOUR, ARM_BOOTS, +2, 0, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 3,
0, 0, 0, 0, 0, 0,
@@ -904,12 +1011,14 @@
"Some soft boots.",
"",
"These boots were specially designed by the Assassin's Guild.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 53: UNRAND_LEAR */
{
"Lear's chain mail", "golden chain mail",
- OBJ_ARMOUR, ARM_CHAIN_MAIL, -1, 0, YELLOW,
+ OBJ_ARMOUR, ARM_CHAIN_MAIL, -1, 0, YELLOW, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, -3,
0, 0, 0, 0, 0, 0,
@@ -921,12 +1030,14 @@
"A chain mail made of pure gold.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 54: UNRAND_ZHOR */
{
"skin of Zhor", "smelly skin",
- OBJ_ARMOUR, ARM_ANIMAL_SKIN, +4, 0, BROWN,
+ OBJ_ARMOUR, ARM_ANIMAL_SKIN, +4, 0, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 0,
@@ -938,12 +1049,14 @@
"The skin of some strange animal.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 55: UNRAND_SALAMANDER */
{
"salamander hide armour", "red leather armour",
- OBJ_ARMOUR, ARM_LEATHER_ARMOUR, +3, 0, RED,
+ OBJ_ARMOUR, ARM_LEATHER_ARMOUR, +3, 0, RED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
2, 0, 0, 0, 0, 0,
@@ -955,12 +1068,14 @@
"A leather armour made of a salamander's skin.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 56: UNRAND_WAR */
{
"gauntlets of War", "thick gauntlets",
- OBJ_ARMOUR, ARM_GLOVES, +3, 0, BROWN,
+ OBJ_ARMOUR, ARM_GLOVES, +3, 0, BROWN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -972,12 +1087,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 57: UNRAND_RESISTANCE */
{
"shield of Resistance", "bronze shield",
- OBJ_ARMOUR, ARM_SHIELD, +3, 0, LIGHTRED,
+ OBJ_ARMOUR, ARM_SHIELD, +3, 0, LIGHTRED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
1, 1, 0, 0, 0, 40,
@@ -989,12 +1106,14 @@
"A bronze shield.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 58: UNRAND_FOLLY */
{
"robe of Folly", "dull robe",
- OBJ_ARMOUR, ARM_ROBE, -1, 0, LIGHTGREY,
+ OBJ_ARMOUR, ARM_ROBE, -1, 0, LIGHTGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, -5, 0,
0, 0, 0, 0, 0, 0,
@@ -1006,12 +1125,14 @@
"A dull grey robe.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 59: UNRAND_MAXWELL */
{
"Maxwell's patent armour", "weird-looking armour",
- OBJ_ARMOUR, ARM_PLATE_MAIL, +10, 0, LIGHTGREEN,
+ OBJ_ARMOUR, ARM_PLATE_MAIL, +10, 0, LIGHTGREEN, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -1023,12 +1144,14 @@
"A weird-looking armour.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 60: UNRAND_DRAGONMASK */
{
"mask of the Dragon", "blue mask",
- OBJ_ARMOUR, ARM_CAP, 0, 0, BLUE,
+ OBJ_ARMOUR, ARM_CAP, 0, 0, BLUE, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 40,
@@ -1040,12 +1163,14 @@
"A blue mask.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 61: UNRAND_NIGHT */
{
"robe of Night", "black robe",
- OBJ_ARMOUR, ARM_ROBE, +4, 0, DARKGREY,
+ OBJ_ARMOUR, ARM_ROBE, +4, 0, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 30,
@@ -1057,12 +1182,14 @@
"A long black robe made of strange glossy material.",
"",
"According to legend, this robe was the gift of Ratri the Goddess of the Night to one of her followers.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 62: UNRAND_DRAGON_KING */
{
"armour of the Dragon King", "shiny dragon armour",
- OBJ_ARMOUR, ARM_GOLD_DRAGON_ARMOUR, +5, 0, YELLOW,
+ OBJ_ARMOUR, ARM_GOLD_DRAGON_ARMOUR, +5, 0, YELLOW, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 50,
@@ -1074,12 +1201,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 63: UNRAND_ALCHEMIST */
{
"hat of the Alchemist", "dirty hat",
- OBJ_ARMOUR, ARM_WIZARD_HAT, +2, 0, MAGENTA,
+ OBJ_ARMOUR, ARM_WIZARD_HAT, +2, 0, MAGENTA, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, 0, 0,
1, 1, 1, 0, 0, 30,
@@ -1091,12 +1220,14 @@
"A dirty hat.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 64: UNRAND_FENCERS_GLOVES */
{
"Fencer's gloves", "silk gloves",
- OBJ_ARMOUR, ARM_GLOVES, +2, 0, WHITE,
+ OBJ_ARMOUR, ARM_GLOVES, +2, 0, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 3, 0, 0, 3,
0, 0, 0, 0, 0, 0,
@@ -1108,12 +1239,14 @@
"A pair of gloves made of white silk.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 65: UNRAND_STARLIGHT */
{
"cloak of Starlight", "phosphorescent cloak",
- OBJ_ARMOUR, ARM_CLOAK, 0, 0, WHITE,
+ OBJ_ARMOUR, ARM_CLOAK, 0, 0, WHITE, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 4, 0, 0, 0,
0, 1, 1, 0, 0, 0,
@@ -1125,12 +1258,14 @@
"A phosphorescent cloak.",
"",
"A cloak woven of pure light beams.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 66: UNRAND_RATSKIN_CLOAK */
{
"ratskin cloak", "motley cloak",
- OBJ_ARMOUR, ARM_CLOAK, +1, 0, LIGHTRED,
+ OBJ_ARMOUR, ARM_CLOAK, +1, 0, LIGHTRED, 0,
+ UNRAND_FLAG_NONE,
{
SPARM_NORMAL, 0, 0, 0, -1, -1,
0, 0, 0, 1, 1, 0,
@@ -1142,12 +1277,14 @@
"",
"",
"An enchantress with a magic loom and way too much time on her hands stitched this cloak from the hides of hundreds of rats, most of them orange. It's a bit awkward to wear and looks rather foolish, but it provides excellent protection from rats of all kinds.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 67: UNRAND_AIR */
{
"amulet of the Air", "sky-blue amulet",
- OBJ_JEWELLERY, AMU_CONTROLLED_FLIGHT, 0, 0, LIGHTCYAN,
+ OBJ_JEWELLERY, AMU_CONTROLLED_FLIGHT, 0, 0, LIGHTCYAN, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 0, 0,
@@ -1159,12 +1296,14 @@
"A sky-blue amulet.",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 68: UNRAND_SHADOWS */
{
"ring of Shadows", "black ring",
- OBJ_JEWELLERY, RING_INVISIBILITY, 0, 0, DARKGREY,
+ OBJ_JEWELLERY, RING_INVISIBILITY, 0, 0, DARKGREY, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 4, 0, 0, 0,
0, 0, 0, 0, 1, 0,
@@ -1176,12 +1315,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 69: UNRAND_CEKUGOB */
{
"amulet of Cekugob", "crystal amulet",
- OBJ_JEWELLERY, AMU_WARDING, 0, 0, LIGHTGREY,
+ OBJ_JEWELLERY, AMU_WARDING, 0, 0, LIGHTGREY, 0,
+ UNRAND_FLAG_NONE,
{
0, 1, 1, 0, 0, 0,
0, 0, 1, 1, 1, 0,
@@ -1193,12 +1334,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 70: UNRAND_FOUR_WINDS */
{
"amulet of the Four Winds", "jade amulet",
- OBJ_JEWELLERY, AMU_CLARITY, 0, 0, LIGHTGREEN,
+ OBJ_JEWELLERY, AMU_CLARITY, 0, 0, LIGHTGREEN, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 100,
@@ -1210,12 +1353,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 71: UNRAND_BLOODLUST */
{
"necklace of Bloodlust", "blood-stained necklace",
- OBJ_JEWELLERY, AMU_RAGE, 0, 0, RED,
+ OBJ_JEWELLERY, AMU_RAGE, 0, 0, RED, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 2, -2, 0,
0, 0, 0, 0, 0, 30,
@@ -1227,12 +1372,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 72: UNRAND_SHAOLIN */
{
"ring of Shaolin", "jade ring",
- OBJ_JEWELLERY, RING_EVASION, +8, 0, LIGHTGREEN,
+ OBJ_JEWELLERY, RING_EVASION, +8, 0, LIGHTGREEN, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -1244,12 +1391,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 73: UNRAND_ROBUSTNESS */
{
"ring of Robustness", "steel ring",
- OBJ_JEWELLERY, RING_PROTECTION, +8, 0, LIGHTGREY,
+ OBJ_JEWELLERY, RING_PROTECTION, +8, 0, LIGHTGREY, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -1261,12 +1410,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 74: UNRAND_MAGE */
{
"ring of the Mage", "sapphire ring",
- OBJ_JEWELLERY, RING_WIZARDRY, 0, 0, LIGHTBLUE,
+ OBJ_JEWELLERY, RING_WIZARDRY, 0, 0, LIGHTBLUE, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 50,
@@ -1278,12 +1429,14 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 75: UNRAND_SHIELDING */
{
"brooch of Shielding", "shield-shaped amulet",
- OBJ_JEWELLERY, AMU_WARDING, 0, 0, LIGHTBLUE,
+ OBJ_JEWELLERY, AMU_WARDING, 0, 0, LIGHTBLUE, 0,
+ UNRAND_FLAG_NONE,
{
0, 4, 4, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -1295,12 +1448,14 @@
"A shield-shaped amulet.",
"",
"Back in the good old days, every adventurer had one of these handy devices. That, and a pony.",
+ NULL, NULL, NULL, NULL, NULL,
},
/* 76: UNRAND_DUMMY2 */
{
"DUMMY UNRANDART 2", "DUMMY UNRANDART 2",
- OBJ_UNASSIGNED, 250, 250, 250, BLACK,
+ OBJ_UNASSIGNED, 250, 250, 250, BLACK, 0,
+ UNRAND_FLAG_NONE,
{
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
@@ -1312,5 +1467,6 @@
"",
"",
"",
+ NULL, NULL, NULL, NULL, NULL,
},
diff --git a/crawl-ref/source/art-data.txt b/crawl-ref/source/art-data.txt
index 4ef7aee41a..feab12a21e 100644
--- a/crawl-ref/source/art-data.txt
+++ b/crawl-ref/source/art-data.txt
@@ -1,7 +1,9 @@
# This file contains the definitions of undrandarts (and what used to be
# fixed artefacts). util/art-data.pl translates this file into
# art-data.h, and also updates the enumeration and NO_UNRANDARTS in
-# unrand.h
+# artefact.h. C/C++ functions which give unrandarts non-standard
+# behaviour are in art-func.h; util/art-data.pl scans art-func.h and
+# puts the function names found into art-data.h
#
# Each artefact definition is separated by one or more blank lines.
#
@@ -70,8 +72,11 @@
# * berserk: Lets wearer evoke berserking ability.
# * blink: Lets wearer evoke the blink ability.
# * cantelep: Lets wearer evoke the teleport ability.
+# * chaotic: Is treated as a chaotic item.
# * cursed: Item is generated cursed.
# * elec: Grants electrical resistance.
+# * evil: Is treated as an evil item.
+# * holy: Is treated as a holy item.
# * inv: Lets wearer evoke invisibility ability.
# * lev: Lets wearer evoke levitation ability.
# * life: Grants negative energy resistance.
@@ -82,6 +87,10 @@
# * poison: Grants poison resistance.
# * rnd_tele: Induces random teleportation.
# * seeinv: Lets wearer see invisible.
+# * special: Artefact is "special": can't be picked up by monsters,
+# can't be affected by Tukima's Dance, generated less
+# frequently than normal randarts, can be generated in the
+# Abyss if its been lost elsewhere.
# * tilerim: Adds a black outline to the tile, see above section.
# ENUM: Forces the artefact's enumeration literal to something specific.
@@ -113,7 +122,9 @@
# increasing with the value of ANGRY.
# APPEAR: Unidentified appearance of artifact.
# COLD: Cold resistance/vulnerability.
-# COLOUR: The colour of the artifact, as listed in defines.h.
+# COLOUR: The colour of the artifact, either as listed in defines.h
+# (e.g., LIGHTRED) or as listed under element_type in view.h
+# (e.g., ETC_FIRE)
# CURSED: The artefact has a one-in-num chance of becoming cursed each
# time it's equipped.
# DAM: Damage modifier (for non-weapon artefacts).
@@ -138,6 +149,7 @@
# See Tiles section above.
# TILE_EQ: The file containing the equipment tile for the player doll as
# defined in rltiles/dc-player.txt. See Tiles section above.
+# VALUE: Modifies the value returned by item_value()
##################################################################
@@ -158,6 +170,8 @@ PLUS: +7/+7
COLOUR: YELLOW
TILE: spwpn_singing_sword
TILE_EQ: singing_sword
+VALUE: 1200
+BOOL: noises, special
DESC_ID: This blessed weapon loves nothing more than to sing to its owner,
whether they want it to or not.
@@ -168,6 +182,8 @@ PLUS: +3/+11
COLOUR: RED
TILE: spwpn_wrath_of_trog
TILE_EQ: axe_trog
+VALUE: 1000
+BOOL: special
DESC_ID: This was the favourite weapon of the old god Trog, before it was
lost one day. It induces a bloodthirsty berserker rage in anyone
who uses it to strike another.
@@ -176,9 +192,11 @@ NAME: Mace of Variability
APPEAR: shimmering mace
OBJ: OBJ_WEAPONS/WPN_MACE
PLUS: 0/0 # Set on generation
-COLOUR: BLACK # Set on generation
+COLOUR: ETC_RANDOM
TILE: spwpn_mace_of_variability
TILE_EQ: mace_of_variability
+VALUE: 700
+BOOL: special
DESC_ID: It is rather unreliable.
NAME: Glaive of Prune
@@ -188,6 +206,8 @@ PLUS: 0/+12
COLOUR: MAGENTA
TILE: spwpn_glaive_of_prune
TILE_EQ: glaive_of_prune
+VALUE: 1000
+BOOL: special
DESC_ID: It is the creation of a mad god, and carries a curse which
transforms anyone possessing it into a prune. Fortunately, the
curse works very slowly, and one can use it briefly with no
@@ -200,7 +220,8 @@ PLUS: 0/0 # Set on wield
COLOUR: RED
TILE: spwpn_sword_of_power
TILE_EQ: sword_of_power
-BOOL: tilerim
+VALUE: 1000
+BOOL: tilerim, special
DESC_ID: It rewards the powerful with power and the meek with weakness.
NAME: Staff of Olgreb
@@ -210,8 +231,9 @@ PLUS: 0/0 # Set on wield
COLOUR: GREEN
TILE: spwpn_staff_of_olgreb
TILE_EQ: olgreb
+VALUE: 1000
BRAND: SPWPN_VENOM
-BOOL: poison
+BOOL: poison, special
DESC_ID: It was the magical weapon wielded by the mighty wizard Olgreb
before he met his fate somewhere within these dungeons. It
increases the ability of its wielder to use venomous magic, and
@@ -224,6 +246,8 @@ PLUS: 0/0 # Set on wield
COLOUR: BROWN
TILE: spwpn_wucad_mu
TILE_EQ: wucad_mu
+VALUE: 1000
+BOOL: special
DESC_ID: Its power varies in proportion to its wielder's intelligence.
Using it can be a bit risky.
@@ -235,6 +259,8 @@ COLOUR: WHITE
TILE: spwpn_vampires_tooth
TILE_EQ: vampires_tooth
BRAND: SPWPN_VAMPIRICISM
+VALUE: 1000
+BOOL: special
DESC_ID: It is lethally vampiric.
NAME: Scythe of Curses
@@ -244,7 +270,9 @@ PLUS: +13/+13
COLOUR: DARKGREY
TILE: spwpn_scythe_of_curses
TILE_EQ: finisher
-BOOL: cursed
+VALUE: 800
+CURSED: 3
+BOOL: special, evil
DESC_ID: This weapon carries a terrible and highly irritating curse.
NAME: Sceptre of Torment
@@ -254,7 +282,8 @@ PLUS: +7/+6
COLOUR: YELLOW
TILE: spwpn_sceptre_of_torment
TILE_EQ: mace_ruby
-BOOL: tilerim
+VALUE: 1200
+BOOL: tilerim, special, evil
DESC_ID: This truly accursed weapon is an instrument of Hell.
NAME: Sword of Zonguldrok
@@ -264,7 +293,8 @@ PLUS: +9/+9
COLOUR: LIGHTGREY
TILE: spwpn_sword_of_zonguldrok
TILE_EQ: zonguldrok
-BOOL: tilerim
+VALUE: 1250
+BOOL: tilerim, special, evil
DESC_ID: This dreadful weapon is used at the user's peril.
NAME: Sword of Cerebov
@@ -274,8 +304,9 @@ PLUS: +6/+6
COLOUR: YELLOW
TILE: spwpn_sword_of_cerebov
TILE_EQ: sword_twist
+VALUE: 2000
BRAND: SPWPN_FLAMING
-BOOL: cursed, tilerim
+BOOL: cursed, tilerim, special, evil
DESC: Eerie flames cover its twisted blade.
NAME: Staff of Dispater
@@ -285,7 +316,8 @@ PLUS: +4/+4
COLOUR: YELLOW
TILE: spwpn_staff_of_dispater
TILE_EQ: dispater
-BOOL: tilerim
+VALUE: 1200
+BOOL: tilerim, special, evil
DESC_ID: This legendary item can unleash the fury of Hell.
NAME: Sceptre of Asmodeus
@@ -295,7 +327,8 @@ PLUS: +7/+7
COLOUR: RED
TILE: spwpn_sceptre_of_asmodeus
TILE_EQ: asmodeus
-BOOL: tilerim
+VALUE: 1500
+BOOL: tilerim, special, evil
DESC_ID: It carries some of the powers of the arch-fiend Asmodeus.
##################### End of old fixed arts.
diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h
new file mode 100644
index 0000000000..20d5694e8d
--- /dev/null
+++ b/crawl-ref/source/art-func.h
@@ -0,0 +1,484 @@
+/*
+ * File: art-func.h
+ * Summary: Functions non-standard unrandarts uses.
+ * Written by: Matthew Cline
+ *
+ * Modified for Crawl Reference by $Author$ on $Date$
+ */
+
+/*
+ * util/art-data.pl scans through this file to grab the functions
+ * non-standard unrandarts use and put them into the unranddata structs
+ * in art-data.h, so the function names must have the form of
+ * _UNRAND_ENUM_func_name() in order to be recognized.
+ */
+
+#ifdef ART_FUNC_H
+#error "art-func.h included twice!"
+#endif
+
+#ifdef ART_DATA_H
+#error "art-func.h must be included before art-data.h"
+#endif
+
+#define ART_FUNC_H
+
+#include "effects.h" // For Sceptre of Torment tormenting
+#include "food.h" // For evokes
+#include "monplace.h" // For Sceptre of Asmodeus evoke
+#include "monstuff.h" // For Scythe of Curses cursing items
+#include "spells3.h" // For Zonguldrok animating dead
+#include "spl-cast.h" // For evokes
+#include "spl-mis.h" // For Staff of Wucad Mu miscasts
+
+/*******************
+ * Helper functions.
+ *******************/
+
+static void _equip_mpr(bool* show_msgs, const char* msg,
+ msg_channel_type chan = MSGCH_PLAIN)
+{
+ bool def_show = true;
+
+ if (show_msgs == NULL)
+ show_msgs = &def_show;
+
+ if (*show_msgs)
+ mpr(msg, chan);
+
+ // Caller shouldn't give any more messages.
+ *show_msgs = false;
+}
+
+/*******************
+ * Unrand functions.
+ *******************/
+
+static void _ASMODEUS_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ did_god_conduct(DID_UNHOLY, 3);
+ }
+}
+
+static bool _evoke_sceptre_of_asmodeus()
+{
+ bool rc = true;
+ if (one_chance_in(21))
+ rc = false;
+ else if (one_chance_in(20))
+ {
+ // Summon devils, maybe a Fiend.
+ const monster_type mon = (one_chance_in(4) ? MONS_FIEND :
+ summon_any_demon(DEMON_COMMON));
+ const bool good_summon = create_monster(
+ mgen_data::hostile_at(mon,
+ you.pos(), 6, 0, true)) != -1;
+
+ if (good_summon)
+ {
+ if (mon == MONS_FIEND)
+ mpr("\"Your arrogance condemns you, mortal!\"");
+ else
+ mpr("The Sceptre summons one of its servants.");
+ }
+ else
+ mpr("The air shimmers briefly.");
+ }
+ else
+ {
+ // Cast a destructive spell.
+ const spell_type spl = static_cast<spell_type>(
+ random_choose_weighted(114, SPELL_BOLT_OF_FIRE,
+ 57, SPELL_LIGHTNING_BOLT,
+ 57, SPELL_BOLT_OF_DRAINING,
+ 12, SPELL_HELLFIRE,
+ 0));
+ your_spells(spl, you.skills[SK_EVOCATIONS] * 8, false);
+ }
+
+ return (rc);
+}
+
+
+static bool _ASMODEUS_evoke(item_def *item, int* pract, bool* did_work,
+ bool* unevokable)
+{
+ if (_evoke_sceptre_of_asmodeus())
+ {
+ make_hungry(200, false, true);
+ *did_work = true;
+ *pract = 1;
+ }
+
+ return (false);
+}
+
+////////////////////////////////////////////////////
+
+// XXX: Defender's resistance to fire being temporarily downgraded is
+// hardcoded in melee_attack::fire_res_apply_cerebov_downgrade()
+
+static void _CEREBOV_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ did_god_conduct(DID_UNHOLY, 3);
+ }
+}
+
+////////////////////////////////////////////////////
+
+static void _CURSES_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "A shiver runs down your spine.");
+}
+
+static void _CURSES_world_reacts(item_def *item)
+{
+ if (one_chance_in(30))
+ curse_an_item(false);
+}
+
+static void _CURSES_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ did_god_conduct(DID_NECROMANCY, 3);
+ }
+}
+
+/////////////////////////////////////////////////////
+
+static void _DISPATER_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ did_god_conduct(DID_UNHOLY, 3);
+ }
+}
+
+static bool _DISPATER_evoke(item_def *item, int* pract, bool* did_work,
+ bool* unevokable)
+{
+ if (you.duration[DUR_DEATHS_DOOR] || !enough_hp(11, true)
+ || !enough_mp(5, true))
+ {
+ return (false);
+ }
+
+ mpr("You feel the staff feeding on your energy!");
+
+ dec_hp( 5 + random2avg(19, 2), false, "Staff of Dispater" );
+ dec_mp( 2 + random2avg(5, 2) );
+ make_hungry(100, false, true);
+
+ int power = you.skills[SK_EVOCATIONS] * 8;
+ your_spells( SPELL_HELLFIRE, power, false );
+
+ *pract = (coinflip() ? 2 : 1);
+ *did_work = true;
+
+ return (false);
+}
+
+////////////////////////////////////////////////////
+
+// XXX: Staff giving a boost to poison spells is hardocded in
+// player_spec_poison()
+
+static void _olgreb_pluses(item_def *item)
+{
+ // Giving Olgreb's staff a little lift since staves of poison have
+ // been made better. -- bwr
+ item->plus = you.skills[SK_POISON_MAGIC] / 3;
+ item->plus2 = item->plus;
+}
+
+static void _OLGREB_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ if (player_can_smell())
+ _equip_mpr(show_msgs, "You smell chlorine.");
+ else
+ _equip_mpr(show_msgs, "The staff glows a sickly green.");
+
+ _olgreb_pluses(item);
+}
+
+static void _OLGREB_unequip(const item_def *item, bool *show_msgs)
+{
+ if (player_can_smell())
+ _equip_mpr(show_msgs, "The smell of chlorine vanishes.");
+ else
+ _equip_mpr(show_msgs, "The staff's sickly green glow vanishes.");
+}
+
+static void _OLGREB_world_reacts(item_def *item)
+{
+ _olgreb_pluses(item);
+}
+
+static bool _OLGREB_evoke(item_def *item, int* pract, bool* did_work,
+ bool* unevokable)
+{
+ if (!enough_mp( 4, true ) || you.skills[SK_EVOCATIONS] < random2(6))
+ return (false);
+
+ dec_mp(4);
+ make_hungry(50, false, true);
+ *pract = 1;
+ *did_work = true;
+
+ int power = 10 + you.skills[SK_EVOCATIONS] * 8;
+
+ your_spells( SPELL_OLGREBS_TOXIC_RADIANCE, power, false );
+
+ if (x_chance_in_y(you.skills[SK_EVOCATIONS] + 1, 10))
+ your_spells( SPELL_VENOM_BOLT, power, false );
+
+ return (false);
+}
+
+////////////////////////////////////////////////////
+
+static void _power_pluses(item_def *item)
+{
+ item->plus = stepdown_value( -4 + (you.hp / 5), 4, 4, 4, 20 );
+ item->plus2 = item->plus;
+}
+
+static void _POWER_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "You sense an aura of extreme power.");
+ _power_pluses(item);
+}
+
+static void _POWER_world_reacts(item_def *item)
+{
+ _power_pluses(item);
+}
+
+////////////////////////////////////////////////////
+
+static void _SINGING_SWORD_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ bool def_show = true;
+
+ if (show_msgs == NULL)
+ show_msgs = &def_show;
+
+ if (!*show_msgs)
+ return;
+
+ if (item_type_known(*item))
+ {
+ mprf(MSGCH_TALK, "%s says, \"Hi! I'm the Singing Sword!\"",
+ item->name(DESC_CAP_THE).c_str());
+ }
+ else
+ mpr("The Singing Sword hums in delight!", MSGCH_TALK);
+
+ *show_msgs = false;
+
+ // Make noisy_equipment() use a special speech database key.
+ item->props[ART_NOISE_KEY] = "Singing Sword";
+}
+
+static void _SINGING_SWORD_unequip(const item_def *item, bool *show_msgs)
+{
+ _equip_mpr(show_msgs, "The Singing Sword sighs.", MSGCH_TALK);
+}
+
+////////////////////////////////////////////////////
+
+static void _PRUNE_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "You feel pruney.");
+}
+
+////////////////////////////////////////////////////
+
+static void _TORMENT_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "A terribly searing pain shoots up your arm!");
+}
+
+static void _TORMENT_world_reacts(item_def *item)
+{
+ if (one_chance_in(200))
+ {
+ torment(TORMENT_SPWLD, you.pos());
+ did_god_conduct(DID_UNHOLY, 1);
+ }
+}
+
+static void _TORMENT_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER && coinflip())
+ {
+ torment(TORMENT_SPWLD, you.pos());
+ did_god_conduct(DID_UNHOLY, 5);
+ }
+}
+
+/////////////////////////////////////////////////////
+
+static void _TROG_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "You feel bloodthirsty!");
+}
+
+static void _TROG_unequip(const item_def *item, bool *show_msgs)
+{
+ _equip_mpr(show_msgs, "You feel less violent.");
+}
+
+static void _TROG_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (coinflip())
+ attacker->go_berserk(false);
+}
+
+////////////////////////////////////////////////////
+
+static void _wucad_miscast(actor* victim, int power,int fail)
+{
+ MiscastEffect(victim, WIELD_MISCAST, SPTYP_DIVINATION, power, fail,
+ "the Staff of Wucad Mu", NH_NEVER);
+}
+
+static void _wucad_pluses(item_def *item)
+{
+ item->plus = std::min(you.intel - 3, 22);
+ item->plus2 = std::min(you.intel / 2, 13);
+}
+
+static void _WUCAD_MU_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _wucad_miscast(&you, 9, 90);
+ _wucad_pluses(item);
+}
+
+static void _WUCAD_MU_unequip(const item_def *item, bool *show_msgs)
+{
+ _wucad_miscast(&you, 9, 90);
+}
+
+static void _WUCAD_MU_world_reacts(item_def *item)
+{
+ _wucad_pluses(item);
+}
+
+static void _WUCAD_MU_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (one_chance_in(9))
+ _wucad_miscast(attacker, random2(9), random2(70));
+}
+
+static bool _WUCAD_MU_evoke(item_def *item, int* pract, bool* did_work,
+ bool* unevokable)
+{
+ if (you.magic_points == you.max_magic_points
+ || you.skills[SK_EVOCATIONS] < random2(25))
+ {
+ return (false);
+ }
+
+ mpr("Magical energy flows into your mind!");
+
+ inc_mp( 3 + random2(5) + you.skills[SK_EVOCATIONS] / 3, false );
+ make_hungry(50, false, true);
+
+ *pract = 1;
+ *did_work = true;
+
+ if (one_chance_in(3))
+ _wucad_miscast(&you, random2(9), random2(70));
+
+ return (false);
+}
+
+///////////////////////////////////////////////////
+
+// XXX: Always getting maximal vampiric drain is harcoded in
+// melee_attack::apply_damage_brand()
+
+static void _VAMPIRES_TOOTH_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ if (you.is_undead != US_UNDEAD)
+ {
+ _equip_mpr(show_msgs,
+ "You feel a strange hunger, and smell blood in the air...");
+ }
+ else
+ _equip_mpr(show_msgs, "You feel strangely empty.");
+
+ // Vampire's Tooth imposes more hunger than a normal vampiric
+ // weapon. Like other vampiric weapons, the hunger is less for
+ // vampires than for other species.
+ if (you.species != SP_VAMPIRE)
+ artefact_set_property(*item, ARTP_METABOLISM, 3);
+ else
+ artefact_set_property(*item, ARTP_METABOLISM, 1);
+}
+
+///////////////////////////////////////////////////
+
+// XXX: Pluses at creation time are hardcoded in make_item_unrandart()
+
+static void _VARIABILITY_world_reacts(item_def *item)
+{
+ do_uncurse_item(*item);
+
+ if (x_chance_in_y(2, 5))
+ item->plus += (coinflip() ? +1 : -1);
+
+ if (x_chance_in_y(2, 5))
+ item->plus2 += (coinflip() ? +1 : -1);
+
+ if (item->plus < -4)
+ item->plus = -4;
+ else if (item->plus > 16)
+ item->plus = 16;
+
+ if (item->plus2 < -4)
+ item->plus2 = -4;
+ else if (item->plus2 > 16)
+ item->plus2 = 16;
+}
+
+///////////////////////////////////////////////////
+
+static void _ZONGULDROK_equip(item_def *item, bool *show_msgs, bool unmeld)
+{
+ _equip_mpr(show_msgs, "You sense an extremely unholy aura.");
+}
+
+static void _ZONGULDROK_world_reacts(item_def *item)
+{
+ if (one_chance_in(5))
+ {
+ animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU);
+ did_god_conduct(DID_NECROMANCY, 1);
+ }
+}
+
+static void _ZONGULDROK_melee_effect(item_def* weapon, actor* attacker,
+ actor* defender, bool mondied)
+{
+ if (attacker->atype() == ACT_PLAYER)
+ {
+ did_god_conduct(DID_NECROMANCY, 3);
+ }
+}
+
+///////////////////////////////////////////////////
+
diff --git a/crawl-ref/source/artefact.cc b/crawl-ref/source/artefact.cc
index f4698f4e05..18d8343723 100644
--- a/crawl-ref/source/artefact.cc
+++ b/crawl-ref/source/artefact.cc
@@ -29,6 +29,7 @@ REVISION("$Rev$");
#include "religion.h"
#include "spl-book.h"
#include "stuff.h"
+#include "view.h" // Elemental colours for unrandarts
#define KNOWN_PROPS_KEY "artefact_known_props"
#define ARTEFACT_PROPS_KEY "artefact_props"
@@ -290,12 +291,13 @@ static std::string _replace_name_parts(const std::string name_in,
// Remember: disallow unrandart creation in Abyss/Pan.
+// Functions defined in art-func.h are referenced in art-data.h
+#include "art-func.h"
+
static unrandart_entry unranddata[] = {
#include "art-data.h"
};
-static FixedVector < bool, NO_UNRANDARTS > unrandart_exist;
-
static unrandart_entry *_seekunrandart( const item_def &item );
bool is_known_artefact( const item_def &item )
@@ -326,7 +328,7 @@ bool is_unrandom_artefact( const item_def &item )
bool is_special_unrandom_artefact( const item_def &item )
{
return (item.flags & ISFLAG_UNRANDART
- && get_unrand_specialness(item.special) == UNRANDSPEC_SPECIAL);
+ && (_seekunrandart(item)->flags & UNRAND_FLAG_SPECIAL));
}
unique_item_status_type get_unique_item_status(const item_def& item)
@@ -1609,16 +1611,20 @@ int find_okay_unrandart(unsigned char aclass, unsigned char atype,
unrand_special_type get_unrand_specialness(int unrand_index)
{
- if (unrand_index >= UNRAND_SINGING_SWORD
- && unrand_index <= UNRAND_ASMODEUS)
+ if (unrand_index < UNRAND_START || unrand_index > UNRAND_LAST)
{
- return (UNRANDSPEC_SPECIAL);
+ return (UNRANDSPEC_NORMAL);
}
+
+ if (unranddata[unrand_index].flags & UNRAND_FLAG_SPECIAL)
+ return (UNRANDSPEC_SPECIAL);
+
return (UNRANDSPEC_NORMAL);
}
unrand_special_type get_unrand_specialness(const item_def &item)
{
+ ASSERT(is_unrandom_artefact(item));
return get_unrand_specialness(item.special);
}
@@ -1970,6 +1976,12 @@ bool make_item_unrandart( item_def &item, int unrand_index )
set_unique_item_status(unrand_index, UNIQ_EXISTS);
+ if (unrand_index == UNRAND_VARIABILITY)
+ {
+ item.plus = random_range(-4, 16);
+ item.plus2 = random_range(-4, 16);
+ }
+
return (true);
}
@@ -1988,7 +2000,7 @@ const char *unrandart_descrip( int which_descrip, const item_def &item )
void artefact_set_properties( item_def &item,
artefact_properties_t &proprt )
{
- ASSERT( is_random_artefact( item ) );
+ ASSERT( is_artefact( item ) );
ASSERT( item.props.exists( ARTEFACT_PROPS_KEY ) );
CrawlVector &rap_vec = item.props[ARTEFACT_PROPS_KEY].get_vector();
@@ -2004,7 +2016,7 @@ void artefact_set_property( item_def &item,
artefact_prop_type prop,
int val )
{
- ASSERT( is_random_artefact( item ) );
+ ASSERT( is_artefact( item ) );
ASSERT( item.props.exists( ARTEFACT_PROPS_KEY ) );
CrawlVector &rap_vec = item.props[ARTEFACT_PROPS_KEY].get_vector();
diff --git a/crawl-ref/source/artefact.h b/crawl-ref/source/artefact.h
index 38ee3344d4..0844c2fc4c 100644
--- a/crawl-ref/source/artefact.h
+++ b/crawl-ref/source/artefact.h
@@ -12,6 +12,10 @@
#include "externs.h"
+// Artefacts which make noise can use this key to use a different
+// speech database key than the default.
+#define ART_NOISE_KEY "art_noise_key"
+
// NOTE: NO_UNRANDARTS is automatically set by util/art-data.pl
#define NO_UNRANDARTS 76
@@ -111,6 +115,15 @@ enum unrand_type
UNRAND_LAST = UNRAND_DUMMY2
};
+enum unrand_flag_type
+{
+ UNRAND_FLAG_NONE = 0x00,
+ UNRAND_FLAG_SPECIAL = 0x01,
+ UNRAND_FLAG_HOLY = 0x02,
+ UNRAND_FLAG_EVIL = 0x04,
+ UNRAND_FLAG_CHAOTIC = 0x08
+};
+
// The following unrandart bits were taken from $pellbinder's mon-util
// code (see mon-util.h & mon-util.cc) and modified (LRH).
struct unrandart_entry
@@ -118,11 +131,15 @@ struct unrandart_entry
const char *name; // true name of unrandart (max 31 chars)
const char *unid_name; // un-id'd name of unrandart (max 31 chars)
- object_class_type base_type; // class of ura
- int sub_type; // type of ura
- int plus; // plus of ura
- int plus2; // plus2 of ura
- int colour; // colour of ura
+ object_class_type base_type;
+ unsigned char sub_type;
+ short plus;
+ short plus2;
+ unsigned char colour; // colour of ura
+
+ short value;
+ unsigned char flags;
+
short prpty[ART_PROPERTIES];
// special description added to 'v' command output (max 31 chars)
@@ -131,6 +148,14 @@ struct unrandart_entry
const char *desc_id;
// special description added to 'v' command output (max 31 chars)
const char *desc_end;
+
+ void (*equip_func)(item_def* item, bool* show_msgs, bool unmeld);
+ void (*unequip_func)(const item_def* item, bool* show_msgs);
+ void (*world_reacts_func)(item_def* item);
+ void (*melee_effects_func)(item_def* item, actor* attacker,
+ actor* defender, bool mondied);
+ bool (*evoke_func)(item_def *item, int* pract, bool* did_work,
+ bool* unevokable);
};
bool is_known_artefact( const item_def &item );
diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc
index a5586fcea7..97d244ee9c 100644
--- a/crawl-ref/source/debug.cc
+++ b/crawl-ref/source/debug.cc
@@ -1370,6 +1370,14 @@ void wizard_create_spec_object()
}
}
+static std::string _art_val_str(const item_def& item)
+{
+ ASSERT(is_artefact(item));
+
+ return make_stringf("art val: %d, item val: %d",
+ artefact_value(item), item_value(item, true));
+}
+
bool get_item_by_name(item_def *item, char* specs,
object_class_type class_wanted, bool create_for_real)
{
@@ -1478,9 +1486,12 @@ bool get_item_by_name(item_def *item, char* specs,
ptr = strcasestr( entry->name, specs );
if (ptr != NULL && item->base_type == class_wanted)
{
- if (create_for_real)
- mpr(entry->name);
make_item_unrandart(*item, index);
+ if (create_for_real)
+ {
+ mprf("%s (%s)", entry->name,
+ _art_val_str(*item).c_str());
+ }
return(true);
}
}
@@ -1935,14 +1946,15 @@ static bool _make_book_randart(item_def &book)
void wizard_value_artefact()
{
- int i = prompt_invent_item( "Value of which randart?", MT_INVLIST, -1 );
+ int i = prompt_invent_item( "Value of which artefact?", MT_INVLIST, -1 );
if (!prompt_failed(i))
{
- if (!is_random_artefact( you.inv[i] ))
+ const item_def& item(you.inv[i]);
+ if (!is_artefact(item))
mpr("That item is not an artefact!");
else
- mprf("randart val: %d", artefact_value(you.inv[i]));
+ mpr(_art_val_str(item).c_str());
}
}
@@ -1968,6 +1980,7 @@ void wizard_create_all_artefacts()
set_ident_flags(item, ISFLAG_IDENT_MASK);
msg::streams(MSGCH_DIAGNOSTICS) << "Made " << item.name(DESC_NOCAP_A)
+ << " (" << _art_val_str(item) << ")"
<< std::endl;
move_item_to_grid(&islot, you.pos());
}
diff --git a/crawl-ref/source/delay.cc b/crawl-ref/source/delay.cc
index 78270aee29..f83feb33f3 100644
--- a/crawl-ref/source/delay.cc
+++ b/crawl-ref/source/delay.cc
@@ -1565,7 +1565,7 @@ void armour_wear_effects(const int item_slot)
}
if (is_artefact(arm))
- use_artefact(arm, melded);
+ use_artefact(arm, NULL, melded);
if (item_cursed(arm) && !melded)
{
diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc
index b3508346fb..2244402d48 100644
--- a/crawl-ref/source/effects.cc
+++ b/crawl-ref/source/effects.cc
@@ -3424,7 +3424,7 @@ void handle_time(long time_delta)
// Exercise stealth skill:
else if (you.burden_state == BS_UNENCUMBERED
&& !you.duration[DUR_BERSERKER]
- && you.unrand_reacts != SPWLD_SHADOW)
+ && !you.attribute[ATTR_SHADOWS])
{
// Diminishing returns for stealth training by waiting.
if ((you.equip[EQ_BODY_ARMOUR] == -1
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index 5b74a77724..4f7e94b236 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -347,9 +347,8 @@ melee_attack::melee_attack(actor *attk, actor *defn,
to_hit(0), base_damage(0), potential_damage(0), damage_done(0),
special_damage(0), aux_damage(0), stab_attempt(false), stab_bonus(0),
weapon(NULL), damage_brand(SPWPN_NORMAL),
- wpn_skill(SK_UNARMED_COMBAT), hands(HANDS_ONE),
- spwld(SPWLD_NONE), hand_half_bonus(false),
- art_props(0), attack_verb("bug"), verb_degree(),
+ wpn_skill(SK_UNARMED_COMBAT), hands(HANDS_ONE), hand_half_bonus(false),
+ art_props(0), unrand_entry(NULL), attack_verb("bug"), verb_degree(),
no_damage_message(), special_damage_message(), unarmed_attack(),
shield(NULL), defender_shield(NULL),
heavy_armour_penalty(0), can_do_unarmed(false),
@@ -378,14 +377,13 @@ void melee_attack::init_attack()
&& is_artefact( *weapon ))
{
artefact_wpn_properties( *weapon, art_props );
+ if (is_unrandom_artefact( *weapon ))
+ unrand_entry = get_unrand_entry(weapon->special);
}
wpn_skill = weapon ? weapon_skill( *weapon ) : SK_UNARMED_COMBAT;
if (weapon)
- {
hands = hands_reqd( *weapon, attacker->body_size() );
- spwld = item_special_wield_effect( *weapon );
- }
shield = attacker->shield();
if (defender)
@@ -536,25 +534,15 @@ void melee_attack::check_autoberserk()
}
}
-void melee_attack::check_special_wield_effects()
+bool melee_attack::check_unrand_effects(bool mondied)
{
- switch (spwld)
+ if (unrand_entry && unrand_entry->melee_effects_func)
{
- case SPWLD_TROG:
- if (coinflip())
- attacker->go_berserk(false);
- break;
-
- case SPWLD_WUCAD_MU:
- if (one_chance_in(9))
- {
- MiscastEffect(attacker, MELEE_MISCAST, SPTYP_DIVINATION,
- random2(9), random2(70), "the Staff of Wucad Mu");
- }
- break;
- default:
- break;
+ unrand_entry->melee_effects_func(weapon, attacker, defender, mondied);
+ return (!defender->alive());
}
+
+ return (false);
}
void melee_attack::identify_mimic(actor *act)
@@ -597,8 +585,6 @@ bool melee_attack::attack()
// The attacker loses nutrition.
attacker->make_hungry(3, true);
- check_special_wield_effects();
-
// Xom thinks fumbles are funny...
if (attacker->fumbles_attack())
{
@@ -1864,38 +1850,12 @@ void melee_attack::player_exercise_combat_skills()
void melee_attack::player_check_weapon_effects()
{
- if (spwld == SPWLD_TORMENT && coinflip())
- {
- torment(TORMENT_SPWLD, you.pos());
- did_god_conduct(DID_UNHOLY, 5);
- }
-
- if (spwld == SPWLD_ZONGULDROK || spwld == SPWLD_CURSE)
- did_god_conduct(DID_NECROMANCY, 3);
-
- if (weapon)
+ if (weapon && weapon->base_type == OBJ_WEAPONS)
{
- if (weapon->base_type == OBJ_WEAPONS)
- {
- if (is_holy_item(*weapon))
- did_god_conduct(DID_HOLY, 1);
- else if (is_demonic(*weapon))
- did_god_conduct(DID_UNHOLY, 1);
- }
-
- if (is_unrandom_artefact(*weapon))
- {
- switch (weapon->special)
- {
- case UNRAND_ASMODEUS:
- case UNRAND_DISPATER:
- case UNRAND_CEREBOV:
- did_god_conduct(DID_UNHOLY, 3);
- break;
- default:
- break;
- }
- }
+ if (is_holy_item(*weapon))
+ did_god_conduct(DID_HOLY, 1);
+ else if (is_demonic(*weapon))
+ did_god_conduct(DID_UNHOLY, 1);
}
}
@@ -1904,6 +1864,8 @@ bool melee_attack::player_monattk_hit_effects(bool mondied)
{
player_check_weapon_effects();
+ mondied = check_unrand_effects(mondied) || mondied;
+
// Thirsty vampires will try to use a stabbing situation to draw blood.
if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED
&& mondied && stab_attempt && stab_bonus > 0
@@ -4867,6 +4829,9 @@ void melee_attack::mons_perform_attack_rounds()
}
}
+ if (check_unrand_effects())
+ break;
+
if (damage_done < 1 && this_round_hit && !shield_blocked)
mons_announce_dud_hit(attk);
diff --git a/crawl-ref/source/fight.h b/crawl-ref/source/fight.h
index 10322818eb..ea55b2dc53 100644
--- a/crawl-ref/source/fight.h
+++ b/crawl-ref/source/fight.h
@@ -105,12 +105,14 @@ public:
item_def *weapon;
int damage_brand; // Can be special even if unarmed (transforms)
int wpn_skill, hands;
- int spwld; // Special wield effects?
bool hand_half_bonus;
- // If weapon is a randart, its properties.
+ // If weapon is an artefact, its properties.
artefact_properties_t art_props;
+ // If a weapon is an unrandart, its unrandart entry.
+ unrandart_entry *unrand_entry;
+
// Attack messages
std::string attack_verb, verb_degree;
std::string no_damage_message;
@@ -157,7 +159,7 @@ private:
bool is_water_attack(const actor *, const actor *) const;
void check_hand_half_bonus_eligible();
void check_autoberserk();
- void check_special_wield_effects();
+ bool check_unrand_effects(bool mondied = false);
void emit_nodmg_hit_message();
void identify_mimic(actor *mon);
diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc
index fc8010879a..d0784ca0f4 100644
--- a/crawl-ref/source/invent.cc
+++ b/crawl-ref/source/invent.cc
@@ -1722,6 +1722,24 @@ bool prompt_failed(int retval, std::string msg)
bool item_is_evokable(const item_def &item, bool known, bool all_wands,
bool msg)
{
+ if (is_unrandom_artefact(item))
+ {
+ const unrandart_entry* entry = get_unrand_entry(item.special);
+
+ if (entry->evoke_func && item_type_known(item))
+ {
+
+ if (item_is_equipped(item))
+ return (true);
+
+ if (msg)
+ mpr("That item can only be evoked when wielded.");
+
+ return (false);
+ }
+ // Unrandart might still be evokable (e.g., reaching)
+ }
+
const bool wielded = (you.equip[EQ_WEAPON] == item.link);
switch (item.base_type)
@@ -1754,26 +1772,6 @@ bool item_is_evokable(const item_def &item, bool known, bool all_wands,
return (true);
}
- if (is_unrandom_artefact(item))
- {
- switch (item.special)
- {
- case UNRAND_ASMODEUS:
- case UNRAND_WUCAD_MU:
- case UNRAND_DISPATER:
- case UNRAND_OLGREB:
- if (!wielded)
- {
- if (msg)
- mpr("That item can only be evoked when wielded.");
- return (false);
- }
- return (true);
-
- default:
- return (false);
- }
- }
if (msg)
mpr("That item cannot be evoked!");
return (false);
diff --git a/crawl-ref/source/it_use2.cc b/crawl-ref/source/it_use2.cc
index 3685469082..ca82d654e9 100644
--- a/crawl-ref/source/it_use2.cc
+++ b/crawl-ref/source/it_use2.cc
@@ -407,52 +407,25 @@ bool unwield_item(bool showMsgs)
return (false);
you.equip[EQ_WEAPON] = -1;
- you.unrand_reacts = SPWLD_NONE;
you.wield_change = true;
you.m_quiver->on_weapon_changed();
+ // Call this first, so that the unrandart func can set showMsgs to
+ // false if it does its own message handling.
+ if (is_artefact( item ))
+ unuse_artefact(item, &showMsgs);
+
if (item.base_type == OBJ_MISCELLANY
&& item.sub_type == MISC_LANTERN_OF_SHADOWS )
{
you.current_vision += 2;
setLOSRadius(you.current_vision);
+ you.attribute[ATTR_SHADOWS] = 0;
}
else if (item.base_type == OBJ_WEAPONS)
{
- if (is_unrandom_artefact( item ))
- {
- switch (item.special)
- {
- case UNRAND_SINGING_SWORD:
- if (showMsgs)
- mpr("The Singing Sword sighs.", MSGCH_TALK);
- break;
- case UNRAND_TROG:
- if (showMsgs)
- mpr("You feel less violent.");
- break;
- case UNRAND_OLGREB:
- item.plus = 0;
- item.plus2 = 0;
- break;
- case UNRAND_WUCAD_MU:
- item.plus = 0;
- item.plus2 = 0;
- MiscastEffect( &you, WIELD_MISCAST, SPTYP_DIVINATION, 9, 90,
- "the Staff of Wucad Mu" );
- break;
- default:
- break;
- }
-
- return (true);
- }
-
const int brand = get_weapon_brand( item );
- if (is_artefact( item ))
- unuse_artefact(item);
-
if (brand != SPWPN_NORMAL)
{
const std::string msg = item.name(DESC_CAP_YOUR);
@@ -622,7 +595,7 @@ void unwear_armour(int slot)
unuse_artefact(item);
}
-void unuse_artefact(const item_def &item)
+void unuse_artefact(const item_def &item, bool *show_msgs)
{
ASSERT( is_artefact( item ) );
@@ -669,5 +642,19 @@ void unuse_artefact(const item_def &item)
true);
if (proprt[ARTP_NOISES] != 0)
- you.unrand_reacts = SPWLD_NONE;
+ you.attribute[ATTR_NOISES] = 0;
+
+ if (is_unrandom_artefact( item ))
+ {
+ const unrandart_entry *entry = get_unrand_entry(item.special);
+
+ if (entry->unequip_func)
+ entry->unequip_func(&item, show_msgs);
+
+ if (entry->world_reacts_func)
+ {
+ equipment_type eq = get_item_slot(item.base_type, item.sub_type);
+ you.unrand_reacts &= ~(1 << eq);
+ }
+ }
}
diff --git a/crawl-ref/source/it_use2.h b/crawl-ref/source/it_use2.h
index f3f4161eca..d5cc61724e 100644
--- a/crawl-ref/source/it_use2.h
+++ b/crawl-ref/source/it_use2.h
@@ -17,7 +17,7 @@
bool potion_effect(potion_type pot_eff, int pow,
bool drank_it = false, bool was_known = true);
-void unuse_artefact(const item_def &item);
+void unuse_artefact(const item_def &item, bool *show_msgs = NULL);
void unwear_armour(int slot);
bool unwield_item(bool showMsgs = true);
diff --git a/crawl-ref/source/it_use3.cc b/crawl-ref/source/it_use3.cc
index 79fa14e527..bbaf27f11d 100644
--- a/crawl-ref/source/it_use3.cc
+++ b/crawl-ref/source/it_use3.cc
@@ -34,9 +34,8 @@ REVISION("$Rev$");
#include "itemprop.h"
#include "mapmark.h"
#include "message.h"
-#include "misc.h"
#include "monplace.h"
-#include "monstuff.h"
+#include "misc.h"
#include "overmap.h"
#include "player.h"
#include "religion.h"
@@ -44,198 +43,136 @@ REVISION("$Rev$");
#include "skills2.h"
#include "spells1.h"
#include "spells2.h"
-#include "spells3.h"
#include "spl-book.h"
#include "spl-cast.h"
-#include "spl-mis.h"
#include "spl-util.h"
#include "state.h"
#include "stuff.h"
#include "view.h"
#include "xom.h"
-void special_wielded()
+// TODO: Let artefacts besides weapons generate noise.
+void noisy_equipment()
{
- item_def& weapon = *you.weapon();
- const int old_plus = weapon.plus;
- const int old_plus2 = weapon.plus2;
- const char old_colour = weapon.colour;
+ if (silenced(you.pos()) || !one_chance_in(20))
+ return;
+
+ std::string msg;
- switch (you.unrand_reacts)
+ const item_def* weapon = you.weapon();
+
+ if (weapon && weapon->props.exists(ART_NOISE_KEY))
{
- case SPWLD_SING:
- case SPWLD_NOISE:
+ const std::string key = weapon->props[ART_NOISE_KEY];
+ msg = getSpeakString(key);
+ if (!msg.empty())
+ {
+ // "Your Singing Sword" sounds disrespectful
+ // (as if there could be more than one!)
+ msg = replace_all(msg, "@Your_weapon@", "@The_weapon@");
+ msg = replace_all(msg, "@your_weapon@", "@the_weapon@");
+ }
+ }
+ else
{
- if (!silenced(you.pos()) && one_chance_in(20))
+ msg = getSpeakString("noisy weapon");
+ if (!msg.empty())
{
- std::string msg;
-
- if (you.unrand_reacts == SPWLD_SING)
- {
- msg = getSpeakString("Singing Sword");
- if (!msg.empty())
- {
- // "Your Singing Sword" sounds disrespectful
- // (as if there could be more than one!)
- msg = replace_all(msg, "@Your_weapon@", "@The_weapon@");
- msg = replace_all(msg, "@your_weapon@", "@the_weapon@");
- }
- }
- else // SPWLD_NOISE
- {
- msg = getSpeakString("noisy weapon");
- if (!msg.empty())
- {
- msg = replace_all(msg, "@Your_weapon@", "Your @weapon@");
- msg = replace_all(msg, "@your_weapon@", "your @weapon@");
- }
- }
-
- // Set appropriate channel (will usually be TALK).
- msg_channel_type channel = MSGCH_TALK;
-
- // Disallow anything with VISUAL in it.
- if (!msg.empty() && msg.find("VISUAL") != std::string::npos)
- msg = "";
-
- if (!msg.empty())
- {
- std::string param = "";
- std::string::size_type pos = msg.find(":");
-
- if (pos != std::string::npos)
- param = msg.substr(0, pos);
-
- if (!param.empty())
- {
- bool match = true;
-
- if (param == "DANGER")
- channel = MSGCH_DANGER;
- else if (param == "WARN")
- channel = MSGCH_WARN;
- else if (param == "SOUND")
- channel = MSGCH_SOUND;
- else if (param == "PLAIN")
- channel = MSGCH_PLAIN;
- else if (param == "SPELL" || param == "ENCHANT")
- msg = ""; // disallow these as well, channel stays TALK
- else if (param != "TALK")
- match = false;
-
- if (match && !msg.empty())
- msg = msg.substr(pos + 1);
- }
- }
-
- if (msg.empty()) // give default noises
- {
- if (you.unrand_reacts == SPWLD_SING)
- msg = "@The_weapon@ sings.";
- else
- {
- channel = MSGCH_SOUND;
- msg = "You hear a strange noise.";
- }
- }
-
- // replace weapon references
- msg = replace_all(msg, "@The_weapon@", "The @weapon@");
- msg = replace_all(msg, "@the_weapon@", "the @weapon@");
- msg = replace_all(msg, "@weapon@", weapon.name(DESC_BASENAME));
- // replace references to player name and god
- msg = replace_all(msg, "@player_name@", you.your_name);
- msg = replace_all(msg, "@player_god@",
- you.religion == GOD_NO_GOD ? "atheism"
- : god_name(you.religion, coinflip()));
-
- mpr(msg.c_str(), channel);
-
- noisy(25, you.pos());
+ msg = replace_all(msg, "@Your_weapon@", "Your @weapon@");
+ msg = replace_all(msg, "@your_weapon@", "your @weapon@");
}
- break;
}
- case SPWLD_CURSE:
- if (one_chance_in(30))
- curse_an_item(false);
- break;
-
- case SPWLD_VARIABLE:
- do_uncurse_item(weapon);
-
- if (x_chance_in_y(2, 5))
- weapon.plus += (coinflip() ? +1 : -1);
+ // Set appropriate channel (will usually be TALK).
+ msg_channel_type channel = MSGCH_TALK;
- if (x_chance_in_y(2, 5))
- weapon.plus2 += (coinflip() ? +1 : -1);
+ // Disallow anything with VISUAL in it.
+ if (!msg.empty() && msg.find("VISUAL") != std::string::npos)
+ msg = "";
- if (weapon.plus < -4)
- weapon.plus = -4;
- else if (weapon.plus > 16)
- weapon.plus = 16;
-
- if (weapon.plus2 < -4)
- weapon.plus2 = -4;
- else if (weapon.plus2 > 16)
- weapon.plus2 = 16;
+ if (!msg.empty())
+ {
+ std::string param = "";
+ std::string::size_type pos = msg.find(":");
- weapon.colour = random_colour();
- break;
+ if (pos != std::string::npos)
+ param = msg.substr(0, pos);
- case SPWLD_TORMENT:
- if (one_chance_in(200))
+ if (!param.empty())
{
- torment(TORMENT_SPWLD, you.pos());
- did_god_conduct(DID_UNHOLY, 1);
+ bool match = true;
+
+ if (param == "DANGER")
+ channel = MSGCH_DANGER;
+ else if (param == "WARN")
+ channel = MSGCH_WARN;
+ else if (param == "SOUND")
+ channel = MSGCH_SOUND;
+ else if (param == "PLAIN")
+ channel = MSGCH_PLAIN;
+ else if (param == "SPELL" || param == "ENCHANT")
+ msg = ""; // disallow these as well, channel stays TALK
+ else if (param != "TALK")
+ match = false;
+
+ if (match && !msg.empty())
+ msg = msg.substr(pos + 1);
}
- break;
+ }
- case SPWLD_ZONGULDROK:
- if (one_chance_in(5))
- {
- animate_dead(&you, 1 + random2(3), BEH_HOSTILE, MHITYOU);
- did_god_conduct(DID_NECROMANCY, 1);
- }
- break;
+ if (msg.empty()) // give default noises
+ {
+ channel = MSGCH_SOUND;
+ msg = "You hear a strange noise.";
+ }
- case SPWLD_POWER:
- weapon.plus = stepdown_value( -4 + (you.hp / 5), 4, 4, 4, 20 );
- weapon.plus2 = weapon.plus;
- break;
+ // replace weapon references
+ if (weapon)
+ {
+ msg = replace_all(msg, "@The_weapon@", "The @weapon@");
+ msg = replace_all(msg, "@the_weapon@", "the @weapon@");
+ msg = replace_all(msg, "@weapon@", weapon->name(DESC_BASENAME));
+ }
+ // replace references to player name and god
+ msg = replace_all(msg, "@player_name@", you.your_name);
+ msg = replace_all(msg, "@player_god@",
+ you.religion == GOD_NO_GOD ? "atheism"
+ : god_name(you.religion, coinflip()));
- case SPWLD_OLGREB:
- // Giving Olgreb's staff a little lift since staves of poison have
- // been made better. -- bwr
- weapon.plus = you.skills[SK_POISON_MAGIC] / 3;
- weapon.plus2 = weapon.plus;
- break;
+ mpr(msg.c_str(), channel);
- case SPWLD_WUCAD_MU:
- weapon.plus = std::min(you.intel - 3, 22);
- weapon.plus2 = std::min(you.intel / 2, 13);
- break;
+ noisy(25, you.pos());
+}
+
+void shadow_lantern_effect()
+{
+ if (x_chance_in_y(player_spec_death() + 1, 8))
+ {
+ create_monster(mgen_data(MONS_SHADOW, BEH_FRIENDLY, 2, 0, you.pos(),
+ MHITYOU));
+ did_god_conduct(DID_NECROMANCY, 1);
+ }
+}
+
+void unrand_reacts()
+{
+ item_def* weapon = you.weapon();
+ const int old_plus = weapon ? weapon->plus : 0;
+ const int old_plus2 = weapon ? weapon->plus2 : 0;
- case SPWLD_SHADOW:
- if (x_chance_in_y(player_spec_death() + 1, 8))
+ for (int i = 0; i < NUM_EQUIP; i++)
+ {
+ if (you.unrand_reacts & (1 << i))
{
- create_monster(
- mgen_data(MONS_SHADOW, BEH_FRIENDLY, 2, 0, you.pos(), MHITYOU));
- did_god_conduct(DID_NECROMANCY, 1);
- }
- break;
+ item_def& item = you.inv[you.equip[i]];
+ unrandart_entry* entry = get_unrand_entry(item.special);
- //case SPWLD_PRUNE:
- default:
- return;
+ entry->world_reacts_func(&item);
+ }
}
- if (old_plus != weapon.plus
- || old_plus2 != weapon.plus2
- || old_colour != weapon.colour)
- {
+ if (weapon && (old_plus != weapon->plus || old_plus2 != weapon->plus2))
you.wield_change = true;
- }
}
static bool _reaching_weapon_attack(const item_def& wpn)
@@ -390,45 +327,6 @@ static bool evoke_horn_of_geryon()
return (rc);
}
-static bool evoke_sceptre_of_asmodeus()
-{
- bool rc = true;
- if (one_chance_in(21))
- rc = false;
- else if (one_chance_in(20))
- {
- // Summon devils, maybe a Fiend.
- const monster_type mon = (one_chance_in(4) ? MONS_FIEND :
- summon_any_demon(DEMON_COMMON));
- const bool good_summon = create_monster(
- mgen_data::hostile_at(mon,
- you.pos(), 6, 0, true)) != -1;
-
- if (good_summon)
- {
- if (mon == MONS_FIEND)
- mpr("\"Your arrogance condemns you, mortal!\"");
- else
- mpr("The Sceptre summons one of its servants.");
- }
- else
- mpr("The air shimmers briefly.");
- }
- else
- {
- // Cast a destructive spell.
- const spell_type spl = static_cast<spell_type>(
- random_choose_weighted(114, SPELL_BOLT_OF_FIRE,
- 57, SPELL_LIGHTNING_BOLT,
- 57, SPELL_BOLT_OF_DRAINING,
- 12, SPELL_HELLFIRE,
- 0));
- your_spells(spl, you.skills[SK_EVOCATIONS] * 8, false);
- }
-
- return (rc);
-}
-
static bool _efreet_flask(int slot)
{
bool friendly = x_chance_in_y(10 + you.skills[SK_EVOCATIONS] / 3, 20);
@@ -825,12 +723,20 @@ bool evoke_item(int slot)
if (!item_is_evokable(item, false, false, true))
return (false);
- int power = 0;
int pract = 0; // By how much Evocations is practised.
bool did_work = false; // Used for default "nothing happens" message.
bool unevokable = false;
- switch (item.base_type)
+ const unrandart_entry *entry = is_unrandom_artefact(item)
+ ? get_unrand_entry(item.special) : NULL;
+
+ if (entry && entry->evoke_func)
+ {
+ ASSERT(item_is_equipped(item));
+ if (entry->evoke_func(&item, &pract, &did_work, &unevokable))
+ return (did_work);
+ }
+ else switch (item.base_type)
{
case OBJ_WANDS:
zap_wand(slot);
@@ -843,92 +749,12 @@ bool evoke_item(int slot)
{
if (_reaching_weapon_attack(item))
{
- pract = 0;
+ pract = 0;
did_work = true;
}
else
return (false);
}
- else if (is_unrandom_artefact(item))
- {
- switch (item.special)
- {
- case UNRAND_DISPATER:
- if (you.duration[DUR_DEATHS_DOOR] || !enough_hp(11, true)
- || !enough_mp(5, true))
- {
- break;
- }
-
- mpr("You feel the staff feeding on your energy!");
-
- dec_hp( 5 + random2avg(19, 2), false, "Staff of Dispater" );
- dec_mp( 2 + random2avg(5, 2) );
- make_hungry(100, false, true);
-
- power = you.skills[SK_EVOCATIONS] * 8;
- your_spells( SPELL_HELLFIRE, power, false );
- pract = (coinflip() ? 2 : 1);
- did_work = true;
- break;
-
- case UNRAND_ASMODEUS:
- if (evoke_sceptre_of_asmodeus())
- {
- make_hungry(200, false, true);
- did_work = true;
- pract = 1;
- }
- break;
-
- case UNRAND_OLGREB:
- if (!enough_mp( 4, true )
- || you.skills[SK_EVOCATIONS] < random2(6))
- {
- break;
- }
-
- dec_mp(4);
- make_hungry(50, false, true);
- pract = 1;
- did_work = true;
-
- power = 10 + you.skills[SK_EVOCATIONS] * 8;
-
- your_spells( SPELL_OLGREBS_TOXIC_RADIANCE, power, false );
-
- if (x_chance_in_y(you.skills[SK_EVOCATIONS] + 1, 10))
- your_spells( SPELL_VENOM_BOLT, power, false );
- break;
-
- case UNRAND_WUCAD_MU:
- if (you.magic_points == you.max_magic_points
- || you.skills[SK_EVOCATIONS] < random2(25))
- {
- break;
- }
-
- mpr("Magical energy flows into your mind!");
-
- inc_mp( 3 + random2(5) + you.skills[SK_EVOCATIONS] / 3, false );
- make_hungry(50, false, true);
- pract = 1;
- did_work = true;
-
- if (one_chance_in(3))
- {
- // NH_NEVER prevents "nothing happens" messages.
- MiscastEffect( &you, NON_MONSTER, SPTYP_DIVINATION,
- random2(9), random2(70),
- "the Staff of Wucad Mu", NH_NEVER );
- }
- break;
-
- default:
- unevokable = true;
- break;
- }
- }
else
unevokable = true;
break;
diff --git a/crawl-ref/source/it_use3.h b/crawl-ref/source/it_use3.h
index 0c492d9a00..7a06550525 100644
--- a/crawl-ref/source/it_use3.h
+++ b/crawl-ref/source/it_use3.h
@@ -36,7 +36,8 @@ bool evoke_item(int slot = -1);
/* ***********************************************************************
* called from: acr
* *********************************************************************** */
-void special_wielded();
-
+void noisy_equipment();
+void shadow_lantern_effect();
+void unrand_reacts();
#endif
diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc
index 28acee0f04..ef82b60635 100644
--- a/crawl-ref/source/item_use.cc
+++ b/crawl-ref/source/item_use.cc
@@ -438,53 +438,6 @@ void warn_shield_penalties()
}
}
-int item_special_wield_effect(const item_def &item)
-{
- if (item.base_type != OBJ_WEAPONS || !is_artefact(item))
- return (SPWLD_NONE);
-
- int i_eff = SPWPN_NORMAL;
- if (is_special_unrandom_artefact( item ))
- i_eff = item.special;
- else if (is_artefact( item ))
- i_eff = artefact_wpn_property(item, ARTP_BRAND);
- else
- i_eff = item.special;
-
- switch (i_eff)
- {
- case UNRAND_SINGING_SWORD:
- return (SPWLD_SING);
-
- case UNRAND_TROG:
- return (SPWLD_TROG);
-
- case UNRAND_CURSES:
- return (SPWLD_CURSE);
-
- case UNRAND_VARIABILITY:
- return (SPWLD_VARIABLE);
-
- case UNRAND_TORMENT:
- return (SPWLD_TORMENT);
-
- case UNRAND_ZONGULDROK:
- return (SPWLD_ZONGULDROK);
-
- case UNRAND_POWER:
- return (SPWLD_POWER);
-
- case UNRAND_OLGREB:
- return (SPWLD_OLGREB);
-
- case UNRAND_WUCAD_MU:
- return (SPWLD_WUCAD_MU);
-
- default:
- return (SPWLD_NONE);
- }
-}
-
// Provide a function for handling initial wielding of 'special'
// weapons, or those whose function is annoying to reproduce in
// other places *cough* auto-butchering *cough*. {gdl}
@@ -508,7 +461,7 @@ void wield_effects(int item_wield_2, bool showMsgs)
you.current_vision -= 2;
setLOSRadius(you.current_vision);
- you.unrand_reacts = SPWLD_SHADOW;
+ you.attribute[ATTR_SHADOWS] = 1;
}
else if (item.sub_type == MISC_HORN_OF_GERYON)
set_ident_flags(item, ISFLAG_IDENT_MASK);
@@ -545,11 +498,12 @@ void wield_effects(int item_wield_2, bool showMsgs)
mpr("You really shouldn't be using a chaotic item like this.");
}
- const bool was_known = item_type_known(item);
+ // Call unrandrt equip func before item is identified.
+ if (artefact)
+ use_artefact(item_wield_2, &showMsgs);
- // Only used for Singing Sword introducing itself
- // (could be extended to other talking weapons...)
- const std::string old_desc = item.name(DESC_CAP_THE);
+ const bool was_known = item_type_known(item);
+ bool known_recurser = false;
set_ident_flags(item, ISFLAG_EQ_WEAPON_MASK);
@@ -557,9 +511,8 @@ void wield_effects(int item_wield_2, bool showMsgs)
if (artefact)
{
- if (!is_special_unrandom_artefact(item))
- special = artefact_wpn_property(item, ARTP_BRAND);
- use_artefact(item_wield_2);
+ special = artefact_wpn_property(item, ARTP_BRAND);
+
if (!was_known)
{
item.flags |= ISFLAG_NOTED_ID;
@@ -571,6 +524,9 @@ void wield_effects(int item_wield_2, bool showMsgs)
take_note(Note(NOTE_ID_ITEM, 0, 0, item.name(DESC_NOCAP_A).c_str(),
origin_desc(item).c_str()));
}
+ else
+ known_recurser = artefact_known_wpn_property(item,
+ ARTP_CURSED);
}
if (special != SPWPN_NORMAL)
@@ -669,59 +625,12 @@ void wield_effects(int item_wield_2, bool showMsgs)
mpr("It is briefly surrounded by shifting shadows.");
break;
- case UNRAND_SINGING_SWORD:
- if (!was_known)
- {
- mprf(MSGCH_TALK, "%s says, "
- "\"Hi! I'm the Singing Sword!\"",
- old_desc.c_str());
- }
- else
- mpr("The Singing Sword hums in delight!", MSGCH_TALK);
- break;
-
- case UNRAND_TROG:
- mpr("You feel bloodthirsty!");
- break;
-
- case UNRAND_CURSES:
- mpr("A shiver runs down your spine.");
- break;
-
- case UNRAND_PRUNE:
- mpr("You feel pruney.");
- break;
-
- case UNRAND_TORMENT:
- mpr("A terribly searing pain shoots up your arm!");
- break;
-
- case UNRAND_ZONGULDROK:
- mpr("You sense an extremely unholy aura.");
- break;
-
- case UNRAND_POWER:
- mpr("You sense an aura of extreme power.");
- break;
-
- case UNRAND_OLGREB:
- if (player_can_smell())
- mpr("You smell chlorine.");
- else
- mpr("The staff glows slightly green.");
- break;
-
- case UNRAND_VAMPIRES_TOOTH:
- if (you.is_undead != US_UNDEAD)
- {
- mpr("You feel a strange hunger, and smell blood in "
- "the air...");
- }
- else
- mpr("You feel strangely empty.");
+ case SPWPN_NORMAL:
break;
default:
+ mprf(MSGCH_ERROR, "Unknown weapon brand %d, please file"
+ "a bug report", special);
break;
}
}
@@ -748,29 +657,16 @@ void wield_effects(int item_wield_2, bool showMsgs)
}
break;
- case UNRAND_CURSES:
- if (!item_cursed(item) && one_chance_in(3))
- do_curse_item(item, false);
- break;
-
- case UNRAND_WUCAD_MU:
- MiscastEffect(&you, WIELD_MISCAST, SPTYP_DIVINATION, 9, 90,
- "the Staff of Wucad Mu" );
- break;
-
default:
break;
}
- if (is_unrandom_artefact(item))
- you.unrand_reacts = item_special_wield_effect(item);
}
if (item_cursed(item))
{
mpr("It sticks to your hand!");
int amusement = 16;
- if (!known_cursed
- && !(was_known && special == UNRAND_CURSES))
+ if (!known_cursed && !known_recurser)
{
amusement *= 2;
god_type god;
@@ -3735,7 +3631,7 @@ void jewellery_remove_effects(item_def &item, bool mesg)
}
if (is_artefact(item))
- unuse_artefact(item);
+ unuse_artefact(item, &mesg);
// Must occur after ring is removed. -- bwr
calc_mp();
@@ -5256,17 +5152,33 @@ void examine_object(void)
mesclr(true);
} // end original_name()
-void use_artefact(unsigned char item_wield_2)
+void use_artefact(unsigned char item_wield_2, bool *show_msgs)
{
- use_artefact( you.inv[ item_wield_2 ] );
+ use_artefact( you.inv[ item_wield_2 ], show_msgs );
}
-void use_artefact(item_def &item, bool unmeld)
+void use_artefact(item_def &item, bool *show_msgs, bool unmeld)
{
#define unknown_proprt(prop) (proprt[(prop)] && !known[(prop)])
ASSERT( is_artefact( item ) );
+ // Call unrandart equip function first, so that it can modify the
+ // artefact's properties before they're applied.
+ if (is_unrandom_artefact( item ))
+ {
+ const unrandart_entry *entry = get_unrand_entry(item.special);
+
+ if (entry->equip_func)
+ entry->equip_func(&item, show_msgs, unmeld);
+
+ if (entry->world_reacts_func)
+ {
+ equipment_type eq = get_item_slot(item.base_type, item.sub_type);
+ you.unrand_reacts |= (1 << eq);
+ }
+ }
+
const bool alreadyknown = item_type_known(item);
const bool dangerous = player_in_a_dangerous_place();
@@ -5362,7 +5274,7 @@ void use_artefact(item_def &item, bool unmeld)
}
if (proprt[ARTP_NOISES])
- you.unrand_reacts = SPWLD_NOISE;
+ you.attribute[ATTR_NOISES] = 1;
if (!alreadyknown && Options.autoinscribe_artefacts)
add_autoinscription(item, artefact_auto_inscription(item));
diff --git a/crawl-ref/source/item_use.h b/crawl-ref/source/item_use.h
index 973286ed52..59fbbc944c 100644
--- a/crawl-ref/source/item_use.h
+++ b/crawl-ref/source/item_use.h
@@ -156,8 +156,8 @@ void wield_effects(int item_wield_2, bool showMsgs);
/* ***********************************************************************
* called from: delay.cc item_use.cc it_use2.cc
* *********************************************************************** */
-void use_artefact( unsigned char item_wield_2 );
-void use_artefact(item_def &item, bool unmeld = false);
+void use_artefact( unsigned char item_wield_2, bool *show_msgs = NULL);
+void use_artefact(item_def &item, bool *show_msgs = NULL, bool unmeld = false);
bool puton_item(int slot);
@@ -181,8 +181,6 @@ int launcher_final_speed(const item_def &launcher,
void warn_shield_penalties();
-int item_special_wield_effect(const item_def &item);
-
bool wearing_slot(int inv_slot);
#ifdef USE_TILE
diff --git a/crawl-ref/source/itemprop.h b/crawl-ref/source/itemprop.h
index 3802983335..fada212748 100644
--- a/crawl-ref/source/itemprop.h
+++ b/crawl-ref/source/itemprop.h
@@ -363,23 +363,6 @@ enum special_ring_type // jewellery mitm[].special values
SPRING_UNRANDART = 201
};
-enum special_wield_type // you.special_wield
-{
- SPWLD_NONE, // 0
- SPWLD_SING,
- SPWLD_TROG,
- SPWLD_CURSE,
- SPWLD_VARIABLE, // 4
- SPWLD_PRUNE, // 5 - implicit in it_use3::special_wielded() {dlb}
- SPWLD_TORMENT, // 6
- SPWLD_ZONGULDROK,
- SPWLD_POWER,
- SPWLD_WUCAD_MU, // 9
- SPWLD_OLGREB, // 10
- SPWLD_SHADOW = 50, // 50
- SPWLD_NOISE // further differentiation useless -> removed (jpeg)
-};
-
enum stave_type
{
// staves
diff --git a/crawl-ref/source/makefile.mgw b/crawl-ref/source/makefile.mgw
index 90b755cef3..ec353b9415 100644
--- a/crawl-ref/source/makefile.mgw
+++ b/crawl-ref/source/makefile.mgw
@@ -218,10 +218,7 @@ $(FSQLLIBA):
#############################################################################
# Build unrandart data
-artefact.h: art-data.txt
- util/art-data.pl
-
-art-data.h: art-data.txt util/art-data.pl
+art-data.h: art-data.txt util/art-data.pl art-func.h
util/art-data.pl
#############################################################################
diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix
index 91df39215c..91c4ce322b 100644
--- a/crawl-ref/source/makefile.unix
+++ b/crawl-ref/source/makefile.unix
@@ -291,10 +291,7 @@ $(FSQLLIBA):
#############################################################################
# Build unrandart data
-artefact.h: art-data.txt
- util/art-data.pl
-
-art-data.h: art-data.txt util/art-data.pl
+art-data.h: art-data.txt util/art-data.pl art-func.h
util/art-data.pl
#############################################################################
diff --git a/crawl-ref/source/makefile_tiles.mgw b/crawl-ref/source/makefile_tiles.mgw
index 67b9801f1b..51afd6612a 100644
--- a/crawl-ref/source/makefile_tiles.mgw
+++ b/crawl-ref/source/makefile_tiles.mgw
@@ -273,10 +273,7 @@ $(FSQLLIBA):
#############################################################################
# Build unrandart data
-artefact.h: art-data.txt
- util/art-data.pl
-
-art-data.h: art-data.txt util/art-data.pl
+art-data.h: art-data.txt util/art-data.pl art-func.h
util/art-data.pl
#############################################################################
diff --git a/crawl-ref/source/makefile_tiles.unix b/crawl-ref/source/makefile_tiles.unix
index 234d02125b..d8cf96cc3d 100644
--- a/crawl-ref/source/makefile_tiles.unix
+++ b/crawl-ref/source/makefile_tiles.unix
@@ -325,10 +325,7 @@ $(FSQLLIBA):
#############################################################################
# Build unrandart data
-artefact.h: art-data.txt
- util/art-data.pl
-
-art-data.h: art-data.txt util/art-data.pl
+art-data.h: art-data.txt util/art-data.pl art-func.h
util/art-data.pl
#############################################################################
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index d42da805ce..62fe64bd73 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -1241,18 +1241,12 @@ int player_hunger_rate(void)
if (you.species != SP_VAMPIRE)
{
if (player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ))
- {
hunger += 6;
- hunger += 3 * player_equip_unrand( UNRAND_VAMPIRES_TOOTH );
- }
}
else
{
if (player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM ))
- {
hunger += 1;
- hunger += 1 * player_equip_unrand( UNRAND_VAMPIRES_TOOTH );
- }
}
// troll leather armour
@@ -3637,7 +3631,7 @@ int check_stealth(void)
return (1000);
#endif
- if (you.unrand_reacts == SPWLD_SHADOW || you.duration[DUR_BERSERKER])
+ if (you.attribute[ATTR_SHADOWS] || you.duration[DUR_BERSERKER])
return (0);
int stealth = you.dex * 3;
@@ -5912,7 +5906,7 @@ void player::init()
disease = 0;
elapsed_time = 0;
rotting = 0;
- unrand_reacts = SPWLD_NONE;
+ unrand_reacts = 0;
synch_time = 0;
magic_contamination = 0;
diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc
index 049c1f7cd6..54fb1c8142 100644
--- a/crawl-ref/source/religion.cc
+++ b/crawl-ref/source/religion.cc
@@ -3424,6 +3424,14 @@ bool is_holy_item(const item_def& item)
{
bool retval = false;
+ if (is_unrandom_artefact(item))
+ {
+ unrandart_entry* entry = get_unrand_entry(item.special);
+
+ if (entry->flags & UNRAND_FLAG_HOLY )
+ return (true);
+ }
+
switch (item.base_type)
{
case OBJ_WEAPONS:
@@ -3450,20 +3458,21 @@ bool is_evil_item(const item_def& item)
{
bool retval = false;
+ if (is_unrandom_artefact(item))
+ {
+ unrandart_entry* entry = get_unrand_entry(item.special);
+
+ if (entry->flags & UNRAND_FLAG_EVIL)
+ return (true);
+ }
+
switch (item.base_type)
{
case OBJ_WEAPONS:
{
const int item_brand = get_weapon_brand(item);
- const int item_eff = item_special_wield_effect(item);
retval = (is_demonic(item)
- || item.special == UNRAND_ASMODEUS
- || item.special == UNRAND_DISPATER
- || item.special == UNRAND_CEREBOV
- || item_eff == SPWLD_CURSE
- || item_eff == SPWLD_TORMENT
- || item_eff == SPWLD_ZONGULDROK
|| item_brand == SPWPN_DRAINING
|| item_brand == SPWPN_PAIN
|| item_brand == SPWPN_VAMPIRICISM
@@ -3507,6 +3516,14 @@ bool is_chaotic_item(const item_def& item)
{
bool retval = false;
+ if (is_unrandom_artefact(item))
+ {
+ unrandart_entry* entry = get_unrand_entry(item.special);
+
+ if (entry->flags & UNRAND_FLAG_CHAOTIC)
+ return (true);
+ }
+
switch (item.base_type)
{
case OBJ_WEAPONS:
diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc
index 48f4a8dd07..30d0907f3f 100644
--- a/crawl-ref/source/shopping.cc
+++ b/crawl-ref/source/shopping.cc
@@ -618,55 +618,16 @@ unsigned int item_value( item_def item, bool ident )
int valued = 0;
+ if (is_unrandom_artefact( item ) &&
+ item_ident( item, ISFLAG_KNOW_PROPERTIES ))
+ {
+ const unrandart_entry *entry = get_unrand_entry(item.special);
+ valued += entry->value;
+ }
+
switch (item.base_type)
{
case OBJ_WEAPONS:
- if (is_unrandom_artefact( item ))
- {
- if (item_ident( item, ISFLAG_KNOW_PROPERTIES ))
- {
- switch (item.special)
- {
- case UNRAND_CEREBOV:
- valued += 2000;
- break;
-
- case UNRAND_ASMODEUS:
- valued += 1500;
- break;
-
- case UNRAND_ZONGULDROK:
- valued += 1250;
- break;
-
- case UNRAND_TORMENT:
- case UNRAND_SINGING_SWORD:
- case UNRAND_DISPATER:
- valued += 1200;
- break;
-
- case UNRAND_PRUNE:
- case UNRAND_TROG:
- valued += 1000;
- break;
-
- case UNRAND_CURSES:
- valued += 800;
- break;
-
- case UNRAND_VARIABILITY:
- valued += 700;
- break;
-
- default:
- valued += 1000;
- break;
- }
- break;
- }
-
- } // end uniques
-
switch (item.sub_type)
{
case WPN_CLUB:
diff --git a/crawl-ref/source/util/art-data.pl b/crawl-ref/source/util/art-data.pl
index bbe4f68cdb..42422c5274 100755
--- a/crawl-ref/source/util/art-data.pl
+++ b/crawl-ref/source/util/art-data.pl
@@ -3,11 +3,13 @@
use strict;
my $line_num = 0;
+my @warnings = ();
my @errors = ();
my @all_artefacts = ();
my %used_names = ();
my %used_appears = ();
my %used_enums = ();
+my %found_funcs = ();
my %field_type = (
AC => "num",
@@ -18,6 +20,7 @@ my %field_type = (
BLINK => "bool",
BRAND => "enum",
CANTELEP => "bool",
+ CHAOTIC => "bool",
COLD => "num",
COLOUR => "enum",
CURSED => "num",
@@ -25,7 +28,9 @@ my %field_type = (
DEX => "num",
ELEC => "bool",
EV => "num",
+ EVIL => "bool",
FIRE => "num",
+ HOLY => "bool",
INT => "num",
INV => "bool",
LEV => "bool",
@@ -42,8 +47,10 @@ my %field_type = (
POISON => "bool",
RND_TELE => "bool",
SEEINV => "bool",
+ SPECIAL => "bool",
STEALTH => "num",
STR => "num",
+ VALUE => "num",
DESC => "str",
DESC_END => "str",
@@ -52,6 +59,14 @@ my %field_type = (
TILE_EQ => "str",
TILERIM => "bool",
+ flags => "flags",
+
+ equip_func => "func",
+ unequip_func => "func",
+ world_reacts_func => "func",
+ melee_effect_func => "func",
+ evoke_func => "func",
+
plus => "num",
plus2 => "num",
base_type => "enum",
@@ -111,6 +126,10 @@ sub finish_art
$artefact->{base_type} ||= "";
$artefact->{sub_type} ||= "";
+ # Handled later
+ $artefact->{flags} = "";
+
+ # Default ego.
if (!exists($artefact->{BRAND}))
{
my $type = $artefact->{base_type} || "";
@@ -129,6 +148,35 @@ sub finish_art
}
}
+ # Fill in function pointers.
+ my $enum = $artefact->{_ENUM};
+ my $funcs;
+ if ($found_funcs{$enum})
+ {
+ $funcs = $found_funcs{$enum};
+ delete($found_funcs{$enum});
+ }
+ else
+ {
+ $funcs = {};
+ }
+
+ foreach my $func_name ("equip", "unequip", "world_reacts", "melee_effect",
+ "evoke")
+ {
+ my $val;
+ if ($funcs->{$func_name})
+ {
+ $val = "_${enum}_$func_name";
+ }
+ else
+ {
+ $val = "NULL";
+ }
+ $artefact->{"${func_name}_func"} = $val;
+ }
+
+ # Default values.
my $field;
foreach $field (@field_list)
{
@@ -159,6 +207,28 @@ sub finish_art
}
}
+ my $flags = "";
+ my $flag;
+ foreach $flag ("SPECIAL", "HOLY", "EVIL", "CHAOTIC")
+ {
+ if ($artefact->{$flag})
+ {
+ $flags .= "UNRAND_FLAG_$flag | ";
+ }
+ }
+
+ if ($flags eq "")
+ {
+ $flags = "UNRAND_FLAG_NONE";
+ }
+ else
+ {
+ chop($flags);
+ chop($flags);
+ chop($flags);
+ }
+ $artefact->{flags} = $flags;
+
delete($artefact->{_FINISHING});
$artefact->{_FINISHED} = 1;
}
@@ -382,7 +452,8 @@ sub process_line
my @art_order = (
"NAME", "APPEAR", "\n",
- "base_type", "sub_type", "plus", "plus2", "COLOUR",
+ "base_type", "sub_type", "plus", "plus2", "COLOUR", "VALUE", "\n",
+ "flags",
"{", "BRAND", "AC", "EV", "STR", "INT", "DEX", "\n",
"FIRE", "COLD", "ELEC", "POISON", "LIFE", "MAGIC", "\n",
@@ -393,7 +464,10 @@ my @art_order = (
"DESC", "\n",
"DESC_ID", "\n",
- "DESC_END"
+ "DESC_END", "\n",
+
+ "equip_func", "unequip_func", "world_reacts_func", "melee_effect_func",
+ "evoke_func"
);
sub art_to_str
@@ -482,6 +556,10 @@ sub write_data
#error "art-data.h included twice!"
#endif
+#ifndef ART_FUNC_H
+#error "art-func.h must be included before art-data.h"
+#endif
+
#define ART_DATA_H
ENDofTEXT
@@ -899,6 +977,93 @@ HEADER_END
close(TILES);
}
+my %valid_func = (
+ equip => 1,
+ unequip => 1,
+ world_reacts => 1,
+ melee_effect => 1,
+ evoke => 1
+);
+
+sub read_funcs
+{
+ unless(open(INPUT, "<art-func.h"))
+ {
+ die "Couldn't open art-func.h for reading: $!\n";
+ }
+
+ while(<INPUT>)
+ {
+ if (/^static .* _([A-Z_]+)_(\S+)\s*\(/)
+ {
+ my $enum = $1;
+ my $func = $2;
+
+ if (!$valid_func{$func})
+ {
+ push(@warnings, "Unrecognized func '$func' for artefact " .
+ "'$enum'");
+ next;
+ }
+
+ $found_funcs{$enum} ||= {};
+ my $func_list = $found_funcs{$enum};
+
+ $func_list->{$func} = 1;
+ }
+ }
+ close(INPUT);
+}
+
+sub read_data
+{
+ unless(open(INPUT, "<art-data.txt"))
+ {
+ die "Couldn't open art-data.txt for reading: $!\n";
+ }
+
+ my $prev_line = "";
+ my $curr_art = {};
+
+ while (<INPUT>)
+ {
+ chomp;
+ $line_num++;
+
+ # Skip comment-only lines
+ next if (/^#/);
+
+ # Strip comments.
+ s/#.*//;
+
+ # Strip trailing whitspace; leading whitespace indicates the
+ # continuation of a string field.
+ s/\s*$//;
+
+ if ($_ =~ /^\s*$/)
+ {
+ if ($prev_line !~ /^\s*$/)
+ {
+ finish_art($curr_art);
+ push(@all_artefacts, $curr_art);
+ $curr_art = {};
+ }
+ }
+ else
+ {
+ process_line($curr_art, $_);
+ }
+ $prev_line = $_;
+ }
+ close(INPUT);
+
+ if (keys(%$curr_art) > 0)
+ {
+ finish_art($curr_art);
+ push(@all_artefacts, $curr_art);
+ }
+}
+
###############################################################3
###############################################################3
###############################################################3
@@ -907,56 +1072,37 @@ chdir("..") if (-e "../art-data.txt");
chdir("source") if (-e "source/art-data.txt");
die "Couldn't find art-data.txt\n" unless (-e "art-data.txt");
+die "Couldn't find art-func.h\n" unless (-e "art-func.h");
die "Couldn't find artefact.h\n" unless (-e "artefact.h");
die "Can't read art-data.txt\n" unless (-r "art-data.txt");
+die "Can't read art-func.h\n" unless (-r "art-func.h");
die "Can't read artefact.h\n" unless (-r "artefact.h");
die "Can't write to artefact.h\n" unless (-w "artefact.h");
die "Can't write to art-data.h\n" if (-e "art-data.h" && !-w "art-data.h");
-unless(open(INPUT, "<art-data.txt"))
-{
- die "Couldn't open art-data.txt for reading: $!\n";
-}
-
-my $prev_line = "";
-my $curr_art = {};
+read_funcs();
+read_data();
-while (<INPUT>)
+if (keys(%found_funcs) > 0)
{
- chomp;
- $line_num++;
-
- # Skip comment-only lines
- next if (/^#/);
-
- # Strip comments.
- s/#.*//;
-
- # Strip trailing whitspace; leading whitespace indicates the
- # continuation of a string field.
- s/\s*$//;
-
- if ($_ =~ /^\s*$/)
- {
- if ($prev_line !~ /^\s*$/)
- {
- finish_art($curr_art);
- push(@all_artefacts, $curr_art);
- $curr_art = {};
- }
- }
- else
+ my $key;
+ foreach $key (keys(%found_funcs))
{
- process_line($curr_art, $_);
+ push(@warnings, "Funcs for unknown artefact enum $key: " .
+ join(", ", keys(%{$found_funcs{$key}})));
}
- $prev_line = $_;
}
-close(INPUT);
-if (keys(%$curr_art) > 0)
+if (@warnings > 0)
{
- finish_art($curr_art);
- push(@all_artefacts, $curr_art);
+ print STDERR "Warning(s):\n";
+
+ my $warn;
+ foreach $warn (@warnings)
+ {
+ print STDERR "$warn\n";
+ }
+ print STDERR "\n";
}
if (@errors > 0)
diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc
index 054abcef1f..57f95c23da 100644
--- a/crawl-ref/source/view.cc
+++ b/crawl-ref/source/view.cc
@@ -1432,7 +1432,7 @@ bool check_awaken(monsters* monster)
if (player_light_armour(true)
&& you.can_see(monster) // to avoid leaking information
&& you.burden_state == BS_UNENCUMBERED
- && you.unrand_reacts != SPWLD_SHADOW
+ && !you.attribute[ATTR_SHADOWS]
&& !mons_wont_attack(monster)
&& !mons_class_flag(monster->type, M_NO_EXP_GAIN)
// If invisible, training happens much more rarely.
@@ -4966,7 +4966,7 @@ std::string screenshot( bool fullscreen )
static int _viewmap_flash_colour()
{
- if (you.unrand_reacts == SPWLD_SHADOW)
+ if (you.attribute[ATTR_SHADOWS])
return (DARKGREY);
else if (you.duration[DUR_BERSERKER])
return (RED);