1 /* SCCS Id: @(#)dothrow.c 3.4 2003/12/04 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* Contains code for 't' (throw) */
10 STATIC_DCL
int throw_obj(struct obj
*, int, int);
11 STATIC_DCL
void autoquiver(void);
12 STATIC_DCL
int gem_accept(struct monst
*, struct obj
*);
13 STATIC_DCL
void tmiss(struct obj
*, struct monst
*);
14 STATIC_DCL
int throw_gold(struct obj
*);
15 STATIC_DCL
void check_shop_obj(struct obj
*,XCHAR_P
,XCHAR_P
,BOOLEAN_P
);
16 STATIC_DCL
void breakobj(struct obj
*,XCHAR_P
,XCHAR_P
,BOOLEAN_P
,BOOLEAN_P
);
17 STATIC_DCL
void breakmsg(struct obj
*,BOOLEAN_P
);
18 STATIC_DCL boolean
toss_up(struct obj
*, BOOLEAN_P
);
19 STATIC_DCL boolean
throwing_weapon(struct obj
*);
20 STATIC_DCL
void sho_obj_return_to_u(struct obj
*obj
);
21 STATIC_DCL boolean
mhurtle_step(void *,int,int);
22 static void autoquiver(void); /* KMH -- automatically fill quiver */
25 static NEARDATA
const char toss_objs
[] =
26 { ALLOW_COUNT
, COIN_CLASS
, ALL_CLASSES
, WEAPON_CLASS
, 0 };
27 /* different default choices when wielding a sling (gold must be included) */
28 static NEARDATA
const char bullets
[] =
29 { ALLOW_COUNT
, COIN_CLASS
, ALL_CLASSES
, GEM_CLASS
, 0 };
31 struct obj
*thrownobj
= 0; /* tracks an object until it lands */
33 extern boolean notonhead
; /* for long worms */
36 #define THROW_USWAPWEP 2
38 /* Split this object off from its slot */
44 struct obj
*obj
= *pobj
;
45 struct obj
*otmp
= (struct obj
*)0;
48 setuqwep(otmp
= splitobj(obj
, 1L));
50 setuqwep((struct obj
*)0);
51 } else if (obj
== uswapwep
) {
53 setuswapwep(otmp
= splitobj(obj
, 1L), FALSE
);
55 setuswapwep((struct obj
*)0, FALSE
);
56 } else if (obj
== uwep
) {
58 setworn(otmp
= splitobj(obj
, 1L), W_WEP
);
59 /* not setuwep; do not change unweapon */
61 setuwep((struct obj
*)0, FALSE
, TRUE
);
62 if (uwep
) return (struct obj
*)0; /* unwielded, died, rewielded */
64 } else if (obj
->quan
> 1L)
65 otmp
= splitobj(obj
, 1L);
70 /* Throw the selected object, asking for direction */
72 throw_obj(obj
, shotlimit
, thrown
)
73 register struct obj
*obj
;
79 int multishot
= (Race_if(PM_CLOCKWORK_AUTOMATON
) && !Upolyd
) ? rnd(3) : Race_if(PM_MANSTER
) ? rnd(2) : Race_if(PM_MONGUNG
) ? rnd(2) : Race_if(PM_HAXOR
) ? rno(2) : 1;
80 boolean fullmultishot
= FALSE
; /* depends on missile weapons skill --Amy */
81 boolean reallyfullmultishot
= FALSE
;
82 int angeramount
; /* for blade anger technique */
84 if (RngeMultishot
) multishot
++;
85 if (Race_if(PM_SPARD
)) multishot
+= rnd(4);
86 if (uarmf
&& uarmf
->oartifact
== ART_ZERO_SUIT
) multishot
+= 1;
87 if (uarmh
&& uarmh
->oartifact
== ART_VIRUS_ATTACK
) multishot
+= 1;
88 if (uarmh
&& uarmh
->oartifact
== ART_SURFACE_TO_AIR_SITE
) multishot
+= 1;
89 if (uwep
&& uwep
->oartifact
== ART_LASER_PALADIN
) multishot
+= 1;
90 if (uarmg
&& uarmg
->oartifact
== ART_WHINY_MARY
) multishot
+= rnd(5);
91 if (uwep
&& uwep
->oartifact
== ART_GUNS_IN_MY_HEAD
) multishot
+= 1;
93 if (Double_attack
|| (uwep
&& uwep
->oartifact
== ART_MELISSA_S_PEACEBRINGER
&& !u
.twoweap
) || (uwep
&& uwep
->oartifact
== ART_CRUSHING_IMPACT
&& !u
.twoweap
) ) multishot
+= rn2(multishot
+ 1);
94 if (Quad_attack
) multishot
+= rn2(multishot
* 3 + 1);
96 if ((long)multishot
> obj
->quan
&& (long)multishot
> 1) multishot
= (int)obj
->quan
;
98 if ((shotlimit
> 0) && (multishot
> shotlimit
)) multishot
= shotlimit
;
104 multi
= 0; /* reset; it's been used up */
106 if (thrown
== 1 && uwep
&& ammo_and_launcher(obj
, uwep
))
108 else if (thrown
== 2 && uswapwep
&& ammo_and_launcher(obj
, uswapwep
))
110 else if (thrown
== 666) { /* inbuilt pistol boots */
111 if (uarmf
&& itemhasappearance(uarmf
, APP_PISTOL_BOOTS
) ) launcher
= uarmf
;
113 else launcher
= (struct obj
*)0;
115 /* ask "in what direction?" */
117 if (!getdir((char *)0)) {
118 if (obj
->oclass
== COIN_CLASS
) {
119 u
.ugold
+= obj
->quan
;
126 if(obj
->oclass
== COIN_CLASS
) return(throw_gold(obj
));
128 if (!getdir((char *)0)) {
129 /* obj might need to be merged back into the singular gold object */
136 Throwing money is usually for getting rid of it when
137 a leprechaun approaches, or for bribing an oncoming
138 angry monster. So throw the whole object.
140 If the money is in quiver, throw one coin at a time,
141 possibly using a sling.
143 if(obj
->oclass
== COIN_CLASS
&& obj
!= uquiver
) return(throw_gold(obj
));
146 if(!canletgo(obj
,"throw"))
149 if(obj
== uwep
&& welded(obj
)) {
154 if (obj
->oartifact
== ART_MJOLLNIR
&& obj
!= uwep
) {
155 pline("%s must be wielded before it can be thrown.",
159 if (obj
->oartifact
== ART_OTHER_MJOLLNIR
&& obj
!= uwep
) {
160 pline("%s must be wielded before it can be thrown.",
164 /* Since it's almost impossible to get 25 strength in slex, valkyries can simply throw Mjollnir at all times --Amy */
165 if ((obj
->oartifact
== ART_MJOLLNIR
&& !Role_if(PM_VALKYRIE
) && !Role_if(PM_VANILLA_VALK
) && ACURR(A_STR
) < STR19(25))
166 || (obj
->otyp
== BOULDER
&& !throws_rocks(youmonst
.data
) && !(uarmg
&& uarmg
->oartifact
== ART_MOUNTAIN_FISTS
) )) {
167 pline("It's too heavy.");
170 if ((obj
->oartifact
== ART_OTHER_MJOLLNIR
&& !Role_if(PM_VALKYRIE
) && !Role_if(PM_VANILLA_VALK
) && ACURR(A_STR
) < STR19(25))
171 || (obj
->otyp
== BOULDER
&& !throws_rocks(youmonst
.data
) && !(uarmg
&& uarmg
->oartifact
== ART_MOUNTAIN_FISTS
) )) {
172 pline("It's too heavy.");
175 if(!u
.dx
&& !u
.dy
&& !u
.dz
) {
176 You("cannot throw an object at yourself.");
180 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && (obj
->otyp
== CORPSE
&&
181 touch_petrifies(&mons
[obj
->corpsenm
]))) {
182 You("throw the %s corpse with your bare %s.",
183 mons
[obj
->corpsenm
].mname
, body_part(HAND
));
184 sprintf(killer_buf
, "throwing a petrifying corpse");
185 instapetrify(killer_buf
);
187 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && (obj
->otyp
== PETRIFYIUM_BAR
)) {
188 You("throw the bar with your bare %s.", body_part(HAND
));
189 sprintf(killer_buf
, "a thrown petrifyium bar");
190 instapetrify(killer_buf
);
192 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && (obj
->otyp
== PETRIFYIUM_BRA
)) {
193 You("throw the bra with your bare %s.", body_part(HAND
));
194 sprintf(killer_buf
, "a thrown petrifyium bra");
195 instapetrify(killer_buf
);
197 if ( (!uarmg
|| FingerlessGloves
) && (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) && (obj
->otyp
== EGG
&&
198 touch_petrifies(&mons
[obj
->corpsenm
]) && obj
->corpsenm
!= PM_PLAYERMON
)) {
199 You("throw the %s egg with your bare %s.",
200 mons
[obj
->corpsenm
].mname
, body_part(HAND
));
201 sprintf(killer_buf
, "throwing a petrifying egg");
202 instapetrify(killer_buf
);
209 /* Multishot calculations
211 skill
= objects
[obj
->otyp
].oc_skill
;
212 if (( (ammo_and_launcher(obj
, uwep
) && !(uwep
&& uwep
->otyp
== LASERXBOW
&& !uwep
->lamplit
) && !(uwep
&& uwep
->otyp
== KLIUSLING
&& !uwep
->lamplit
) ) || skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_BOOMERANG
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
||
213 skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== P_SPEAR
|| skill
== P_JAVELIN
) &&
214 !( (Confusion
&& !Conf_resist
) || (Stunned
&& !Stun_resist
) )) {
215 /* Bonus if the player is proficient in this weapon... */
217 if (!(PlayerCannotUseSkills
)) {
219 switch (P_SKILL(weapon_type(obj
))) {
220 default: break; /* No bonus */
221 case P_SKILLED
: multishot
++; break;
222 case P_EXPERT
: multishot
+= 2; break;
223 case P_MASTER
: multishot
+= 3; break; /* this might be implemented --Amy */
224 case P_GRAND_MASTER
: multishot
+= 4; break;
225 case P_SUPREME_MASTER
: multishot
+= 5; break;
230 /* ...or is using a good weapon... */
231 /* Elven Craftsmanship makes for light, quick bows */
232 if (obj
->otyp
== ELVEN_ARROW
&& !obj
->cursed
&& !rn2(3)) multishot
++;
233 if (launcher
&& launcher
->otyp
== ELVEN_BOW
&&
234 !launcher
->cursed
&& !rn2(3))
237 if (launcher
&& launcher
->oartifact
== ART_MULTISHOTTEMSO
&& launcher
->lamplit
&& !(PlayerCannotUseSkills
)) {
238 switch (P_SKILL(P_DJEM_SO
)) {
239 default: break; /* No bonus */
240 case P_BASIC
: multishot
++; break;
241 case P_SKILLED
: multishot
+= 2; break;
242 case P_EXPERT
: multishot
+= 3; break;
243 case P_MASTER
: multishot
+= 4; break;
244 case P_GRAND_MASTER
: multishot
+= 5; break;
245 case P_SUPREME_MASTER
: multishot
+= 6; break;
249 if (launcher
&& launcher
->oartifact
== ART_CANNONDANCER
&& !(PlayerCannotUseSkills
)) {
250 switch (P_SKILL(P_FIREARM
)) {
251 default: break; /* No bonus */
252 case P_BASIC
: multishot
+= 1; break;
253 case P_SKILLED
: multishot
+= rnd(2); break;
254 case P_EXPERT
: multishot
+= rnd(3); break;
255 case P_MASTER
: multishot
+= rnd(4); break;
256 case P_GRAND_MASTER
: multishot
+= rnd(5); break;
257 case P_SUPREME_MASTER
: multishot
+= rnd(6); break;
261 if (launcher
&& launcher
->oartifact
== ART_EXPERIMENTAL_MIRV
) {
263 fullmultishot
= TRUE
;
264 reallyfullmultishot
= TRUE
;
267 if (launcher
&& launcher
->otyp
== WILDHILD_BOW
&& obj
->otyp
== ODOR_SHOT
) multishot
++;
268 if (launcher
&& launcher
->otyp
== COMPOST_BOW
&& obj
->otyp
== FORBIDDEN_ARROW
) multishot
++;
270 if (launcher
&& launcher
->oartifact
== ART_TEAM_FORTRESS_GL
&& obj
->otyp
== FRAG_GRENADE
) multishot
+= 5;
271 if (launcher
&& launcher
->oartifact
== ART_TEAM_FORTRESS_GL
&& obj
->otyp
== GAS_GRENADE
) multishot
+= 5;
273 if (launcher
&& launcher
->oartifact
== ART_MEASURE_SKILLING
) multishot
++;
274 if (launcher
&& launcher
->oartifact
== ART_SKILLED_THROUGHLOAD
) multishot
++;
275 if (launcher
&& launcher
->oartifact
== ART_LINCOLN_S_REPEATER
) multishot
++;
276 if (launcher
&& launcher
->oartifact
== ART_AR_ARMALYTE
) multishot
++;
277 if (launcher
&& launcher
->oartifact
== ART_LOUD_SHITTER
) multishot
+= rn1(2, 2);
278 if (launcher
&& launcher
->oartifact
== ART_CLACKINDRA
) multishot
+= 3;
279 if (launcher
&& launcher
->oartifact
== ART_UZ_I
) multishot
+= rnd(3);
280 if (launcher
&& launcher
->oartifact
== ART_HEAVY_CROSSBOW_OF_ETERNITY
) multishot
+= 2;
281 if (launcher
&& obj
&& obj
->oartifact
== ART_FUCK_THE_SERVER
) multishot
+= 2;
283 if (uarmf
&& uarmf
->oartifact
== ART_FRENCHYPOSS
&& uarmf
->blessed
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) multishot
++;
285 if (uarms
&& uarms
->oartifact
== ART_MISSING_LETTER_D
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_SLING
) multishot
+= 2;
287 if (launcher
&& launcher
->oartifact
== ART_NOCK_GUN
&& (launcher
->invoketimer
<= monstermoves
) ) {
288 int artitimeout
= rnz(2000);
289 if (!rn2(5)) artitimeout
= rnz(20000); /* squeaking does not help here, as it's not an actual invoke --Amy */
291 launcher
->invoketimer
= (monstermoves
+ artitimeout
);
294 if (obj
&& obj
->oartifact
== ART_WIWIU_
) multishot
+= rnd(3);
295 if (obj
&& obj
->oartifact
== ART_LEAD_SYRINGE
) multishot
+= 2;
296 if (obj
&& obj
->otyp
== RAPID_DART
) multishot
+= 2;
297 if (obj
&& obj
->otyp
== NINJA_STAR
) multishot
+= 3;
298 if (obj
&& obj
->otyp
== FLAMETHROWER
) multishot
+= 4;
299 if (obj
&& obj
->oartifact
== ART_POEPOEPOEPOEOEU_
) multishot
+= 4;
300 if (obj
&& obj
->oartifact
== ART_MRLS
) multishot
+= 1;
301 if (obj
&& obj
->oartifact
== ART_FRIGHT_PRAWN
) multishot
+= 1;
302 if (obj
&& obj
->oartifact
== ART_WASHINGTON_S_CAPPER
) multishot
+= 1;
303 if (uarmh
&& uarmh
->oartifact
== ART_GIVE_THE_BONUS_STUFF
) multishot
+= 1;
305 if (obj
&& obj
->oartifact
== ART_CAPAUER
&& !PlayerCannotUseSkills
) {
306 if (P_MAX_SKILL(P_SHURIKEN
) == P_SUPREME_MASTER
) {
307 switch (P_SKILL(P_SHURIKEN
)) {
308 case P_GRAND_MASTER
: multishot
+= 1; break;
309 case P_MASTER
: multishot
+= 2; break;
310 case P_EXPERT
: multishot
+= 3; break;
312 } else if (P_MAX_SKILL(P_SHURIKEN
) == P_GRAND_MASTER
) {
313 switch (P_SKILL(P_SHURIKEN
)) {
314 case P_MASTER
: multishot
+= 1; break;
315 case P_EXPERT
: multishot
+= 2; break;
317 } else if (P_MAX_SKILL(P_SHURIKEN
) == P_MASTER
) {
318 switch (P_SKILL(P_SHURIKEN
)) {
319 case P_EXPERT
: multishot
+= 1; break;
325 if (Race_if(PM_AZTPOK
) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) multishot
+= rnd(2);
326 if (Race_if(PM_TURMENE
) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) multishot
+= rnd(3);
328 if (uamul
&& uamul
->oartifact
== ART_PURPLE_ARBALEST
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_CROSSBOW
) multishot
++;
329 if (uamul
&& uamul
->oartifact
== ART_PURPLE_ARBALEST
) multishot
++;
331 if (uimplant
&& uimplant
->oartifact
== ART_BIUUU_
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_CROSSBOW
) multishot
++;
332 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_BIUUU_
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) multishot
++;
333 if (uarmh
&& uarmh
->oartifact
== ART_HELM_OF_THE_ARCANE_ARCHER
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) multishot
++;
335 if (launcher
&& objects
[launcher
->otyp
].oc_skill
== P_FIREARM
&& !(PlayerCannotUseSkills
) && P_SKILL(P_SQUEAKING
) >= P_MASTER
&& P_SKILL(P_GUN_CONTROL
) >= P_MASTER
&& Upolyd
) {
337 if (P_SKILL(P_SQUEAKING
) >= P_GRAND_MASTER
&& P_SKILL(P_GUN_CONTROL
) >= P_GRAND_MASTER
) multishot
++;
338 if (P_SKILL(P_SQUEAKING
) >= P_SUPREME_MASTER
&& P_SKILL(P_GUN_CONTROL
) >= P_SUPREME_MASTER
) multishot
++;
341 if (launcher
&& launcher
->otyp
== CATAPULT
&& (!obj
|| obj
->otyp
!= ROCK
)) multishot
+= rnd(5);
342 if (launcher
&& launcher
->otyp
== CATAPULT
&& obj
&& obj
->otyp
== ROCK
) multishot
+= rno(5);
343 if (launcher
&& launcher
->oartifact
== ART_DRIVE_BY
&& u
.usteed
) {
345 if (u
.ugallop
) multishot
++;
347 if (launcher
&& launcher
->oartifact
== ART_BROWNING
) multishot
+= rnd(5);
349 if ((uwep
&& uwep
->oartifact
== ART_SPEERTHROW
) && (skill
== P_SPEAR
) ) {
351 if (Race_if(PM_AZTPOK
) || Race_if(PM_MAYMES
)) multishot
++;
354 if (uwep
&& uwep
->oartifact
== ART_POWCHARGE
) multishot
++;
356 if (launcher
&& (launcher
->otyp
== RIFLE
|| launcher
->otyp
== SNIPER_RIFLE
|| launcher
->otyp
== HUNTING_RIFLE
|| launcher
->otyp
== PROCESS_CARD
) && uarmc
&& itemhasappearance(uarmc
, APP_RIFLING_POWER_CLOAK
) ) multishot
+= rnd(2);
358 if (launcher
&& launcher
->otyp
== HYDRA_BOW
) multishot
+= 2;
359 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& launcher
->altmode
== WP_MODE_AUTO
) multishot
+= 4;
360 if (launcher
&& launcher
->otyp
== WILDHILD_BOW
) multishot
+= 2;
362 if (launcher
&& launcher
->oartifact
== ART_STREAMSHOOTER
) multishot
+= 1;
364 if (launcher
&& launcher
->oartifact
== ART_SNIPEGIANT
) multishot
+= 1;
365 if (launcher
&& launcher
->oartifact
== ART_DOLE__EM_ALL_OUT
) multishot
+= 2;
367 if (launcher
&& launcher
->oartifact
== ART_MAXIMUM_LAUNCH_POWER
) multishot
+= rnd(2);
369 if (launcher
&& launcher
->oartifact
== ART_WINSETT_S_BIG_DADDY
) multishot
+= rnd(2);
371 if (launcher
&& launcher
->oartifact
== ART_TUNA_CANNON
) multishot
+= 1;
373 if (launcher
&& launcher
->oartifact
== ART_FOEOEOEOEOEOEOE
) multishot
+= rnd(3);
375 if (!PlayerCannotUseSkills
&& skill
== P_SLING
&& ((uarm
&& uarm
->oartifact
== ART_LU_NONNAME
) || Role_if(PM_HEDDERJEDI
)) ) {
376 if (u
.kliuskill
>= 20) multishot
++;
377 if (u
.kliuskill
>= 160) multishot
++;
378 if (u
.kliuskill
>= 540) multishot
++;
379 if (u
.kliuskill
>= 1280) multishot
++;
380 if (u
.kliuskill
>= 2500) multishot
++;
381 if (u
.kliuskill
>= 4320) multishot
++;
384 if (Role_if(PM_TOSSER
) && obj
&& objects
[obj
->otyp
].oc_skill
== P_JAVELIN
) multishot
+= 1;
385 if (Role_if(PM_MILL_SWALLOWER
) && obj
&& (objects
[obj
->otyp
].oc_skill
== P_CROSSBOW
|| objects
[obj
->otyp
].oc_skill
== -P_CROSSBOW
)) multishot
+= 1;
387 if (uarmg
&& uarmg
->oartifact
== ART_PEEPING_GROOVE
&& launcher
&& (launcher
->otyp
== SHOTGUN
|| launcher
->otyp
== PAPER_SHOTGUN
|| launcher
->otyp
== SAWED_OFF_SHOTGUN
|| launcher
->otyp
== AUTO_SHOTGUN
)) multishot
+= rnd(7);
389 if (uarmc
&& uarmc
->oartifact
== ART_PALEOLITHIC_ELBOW_CONTRACT
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) multishot
+= 5;
391 if (uamul
&& uamul
->oartifact
== ART_WILDWEST_LAW
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) multishot
+= 1;
393 /* 1/3 of object enchantment */
394 if (launcher
&& launcher
->spe
> 1)
395 multishot
+= (long) rounddiv(launcher
->spe
,3);
397 /* ...or is using a special weapon for their role... */
398 switch (Role_switch
) {
403 if (skill
== P_DAGGER
) multishot
++;
406 if (skill
== P_SLING
) multishot
++;
409 if (skill
== P_SLING
) {multishot
++;
411 if (!(PlayerCannotUseSkills
)) {
413 if (P_SKILL(weapon_type(obj
)) >= P_SKILLED
) multishot
++;
414 if (P_SKILL(weapon_type(obj
)) >= P_EXPERT
) multishot
++;
415 if (P_SKILL(weapon_type(obj
)) >= P_MASTER
) multishot
++;
416 if (P_SKILL(weapon_type(obj
)) >= P_GRAND_MASTER
) multishot
++;
417 if (P_SKILL(weapon_type(obj
)) >= P_SUPREME_MASTER
) multishot
++;
422 case PM_ELPH
: /* elf role --Amy */
424 if (obj
->otyp
== ELVEN_ARROW
&& launcher
&&
425 launcher
->otyp
== ELVEN_BOW
) multishot
++;
427 case PM_TWELPH
: /* dark elf role --Amy */
429 if (obj
->otyp
== DARK_ELVEN_ARROW
&& launcher
&&
430 launcher
->otyp
== DARK_ELVEN_BOW
) multishot
++;
433 if (obj
->otyp
== YA
&& launcher
&& launcher
->otyp
== YUMI
) multishot
++;
434 if (obj
->otyp
== FAR_EAST_ARROW
&& launcher
&& launcher
->otyp
== YUMI
) multishot
++;
437 break; /* No bonus */
439 /* ...or using their race's special bow */
440 switch (Race_switch
) {
442 case PM_PLAYER_MYRKALFR
:
443 if (obj
->otyp
== ELVEN_ARROW
&& launcher
&&
444 launcher
->otyp
== ELVEN_BOW
) multishot
++;
446 case PM_PLAYABLE_NEANDERTHAL
:
447 if (skill
== P_SLING
) multishot
++;
450 if (launcher
&& launcher
->otyp
== INKA_SLING
&& ammo_and_launcher(obj
, launcher
) ) multishot
+= 2;
453 if (obj
->otyp
== ORCISH_ARROW
&& uwep
&&
454 uwep
->otyp
== ORCISH_BOW
) multishot
++;
456 case PM_HOBBIT
: /* slings are retarded weapons according to Jacob Black, so a little bonus is in order... --Amy */
457 if (skill
== P_SLING
) multishot
++;
460 break; /* No bonus */
463 if (!(PlayerCannotUseSkills
)) {
465 switch (P_SKILL(P_MISSILE_WEAPONS
)) {
466 /* These fallthroughs are intentional --Amy */
467 case P_SUPREME_MASTER
:
468 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
469 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
470 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
472 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
473 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
474 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
476 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
477 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
478 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
480 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
481 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
482 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
484 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
485 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
486 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
488 if ((skill
== P_DAGGER
|| skill
== P_KNIFE
|| skill
== P_SPEAR
) && !rn2(5)) multishot
++;
489 if (skill
== P_JAVELIN
&& !rn2(3)) multishot
++;
490 if ((skill
== P_DART
|| skill
== P_SHURIKEN
|| skill
== P_BOOMERANG
|| skill
== -P_DART
|| skill
== -P_SHURIKEN
|| skill
== -P_BOOMERANG
|| skill
== P_VENOM
|| skill
== -P_VENOM
) && !rn2(4)) multishot
++;
495 if ((long)multishot
> obj
->quan
) multishot
= (int)obj
->quan
;
498 multishot
= rnd(multishot
); /* Some randomness */
502 if ( (objects
[obj
->otyp
].oc_skill
== -P_BOW
|| objects
[obj
->otyp
].oc_skill
== -P_CROSSBOW
|| objects
[obj
->otyp
].oc_skill
== -P_SLING
) && tech_inuse(T_FLURRY
)) {
503 multishot
+= 1; multishot
+= rnd(multishot
); /* Let'em rip! Extra bonus added by Amy. */
505 /* more than usual == volley */
506 if (((shotlimit
<= 0) || (shotlimit
>= multishot
)) &&
507 (obj
->quan
>= multishot
))
508 You("let fly a volley of %s!", xname(obj
));
511 if ( (objects
[obj
->otyp
].oc_skill
== -P_DAGGER
|| objects
[obj
->otyp
].oc_skill
== P_DAGGER
|| objects
[obj
->otyp
].oc_skill
== -P_DART
|| objects
[obj
->otyp
].oc_skill
== P_DART
|| objects
[obj
->otyp
].oc_skill
== -P_SHURIKEN
|| objects
[obj
->otyp
].oc_skill
== P_SHURIKEN
|| objects
[obj
->otyp
].oc_skill
== -P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== -P_VENOM
|| objects
[obj
->otyp
].oc_skill
== P_VENOM
|| objects
[obj
->otyp
].oc_skill
== -P_KNIFE
|| objects
[obj
->otyp
].oc_skill
== P_KNIFE
|| objects
[obj
->otyp
].oc_skill
== -P_SPEAR
|| objects
[obj
->otyp
].oc_skill
== P_SPEAR
|| objects
[obj
->otyp
].oc_skill
== -P_JAVELIN
|| objects
[obj
->otyp
].oc_skill
== P_JAVELIN
) && uarmf
&& uarmf
->oartifact
== ART_H__S_GANGSTER_KICKS
) {
515 if ( (objects
[obj
->otyp
].oc_skill
== -P_DAGGER
|| objects
[obj
->otyp
].oc_skill
== P_DAGGER
|| objects
[obj
->otyp
].oc_skill
== -P_DART
|| objects
[obj
->otyp
].oc_skill
== P_DART
|| objects
[obj
->otyp
].oc_skill
== -P_SHURIKEN
|| objects
[obj
->otyp
].oc_skill
== P_SHURIKEN
|| objects
[obj
->otyp
].oc_skill
== -P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== -P_VENOM
|| objects
[obj
->otyp
].oc_skill
== P_VENOM
|| objects
[obj
->otyp
].oc_skill
== -P_KNIFE
|| objects
[obj
->otyp
].oc_skill
== P_KNIFE
|| objects
[obj
->otyp
].oc_skill
== -P_SPEAR
|| objects
[obj
->otyp
].oc_skill
== P_SPEAR
|| objects
[obj
->otyp
].oc_skill
== -P_JAVELIN
|| objects
[obj
->otyp
].oc_skill
== P_JAVELIN
) && tech_inuse(T_DOUBLE_THROWNAGE
)) {
516 multishot
+= 1; multishot
+= rnd(multishot
); /* Let'em rip! Extra bonus added by Amy. */
518 /* more than usual == volley */
519 if (((shotlimit
<= 0) || (shotlimit
>= multishot
)) &&
520 (obj
->quan
>= multishot
))
521 You("throw a hail of %s!", xname(obj
));
524 if (launcher
&& launcher
->oartifact
== ART_ARROW_RAIN
&& (launcher
->invoketimer
<= monstermoves
) ) {
525 int artitimeout
= rnz(2000);
526 if (!rn2(5)) artitimeout
= rnz(20000); /* squeaking does not help here, as it's not an actual invoke --Amy */
528 fullmultishot
= TRUE
;
529 reallyfullmultishot
= TRUE
;
530 launcher
->invoketimer
= (monstermoves
+ artitimeout
);
533 if (launcher
&& launcher
->otyp
== PISTOL_PAIR
) multishot
*= 2;
535 /* Shotlimit controls your rate of fire */
536 if ((shotlimit
> 0) && (multishot
> shotlimit
)) multishot
= shotlimit
;
538 if (uarm
&& uarm
->oartifact
== ART_POWASPEL
) {
540 if (multishot
< 1) multishot
= 1;
543 if (launcher
&& launcher
->oartifact
== ART_DESERT_EAGLE
) {
545 if (multishot
< 1) multishot
= 1;
547 if (launcher
&& launcher
->oartifact
== ART_LEONE_M__GUAGE_SUPER
) {
549 if (multishot
< 1) multishot
= 1;
551 if (launcher
&& launcher
->otyp
== BLADE_BOW
) {
553 if (multishot
< 1) multishot
= 1;
555 if (obj
&& obj
->otyp
== HEAVY_SPEAR
) {
557 if (multishot
< 1) multishot
= 1;
559 if (obj
&& obj
->otyp
== SUPERHEAVY_SPEAR
) {
561 if (multishot
< 1) multishot
= 1;
563 if (launcher
&& launcher
->oartifact
== ART_MOSIN_NAGANT
) {
565 if (multishot
< 1) multishot
= 1;
567 if (launcher
&& launcher
->oartifact
== ART_BOW_OF_SKADI
) {
569 if (multishot
< 1) multishot
= 1;
571 if (launcher
&& launcher
->otyp
== SHOVEL
) {
573 if (multishot
< 1) multishot
= 1;
575 if (launcher
&& launcher
->oartifact
== ART_OZYZEVPDWTVP
) {
577 if (multishot
< 1) multishot
= 1;
579 if (uarmc
&& uarmc
->oartifact
== ART_OLD_PERSON_TALK
) {
581 if (multishot
< 1) multishot
= 1;
583 if (uarms
&& uarms
->otyp
== COMPLETE_BLOCKAGE_SHIELD
) {
586 if (multishot
< 1) multishot
= 1;
589 /* Rate of fire is intrinsic to the weapon - cannot be user selected
591 * Only for valid launchers
592 * (currently oc_rof conflicts with wsdam)
594 if (launcher
&& is_launcher(launcher
))
596 if (objects
[(launcher
->otyp
)].oc_rof
&& launcher
->oartifact
!= ART_EXPERIMENTAL_MIRV
)
597 multishot
+= (objects
[(launcher
->otyp
)].oc_rof
- 1);
598 if (launcher
->altmode
== WP_MODE_SINGLE
)
599 /* weapons switchable b/w full/semi auto */
601 else if (launcher
->altmode
== WP_MODE_BURST
)
602 multishot
= ((multishot
> 3) ? (multishot
/ 3) : 1);
603 /* else it is auto == no change */
605 if (objects
[(launcher
->otyp
)].oc_rof
) {
606 if (launcher
->altmode
== WP_MODE_AUTO
&& obj
->quan
< objects
[(launcher
->otyp
)].oc_rof
) {
607 pline("You do not have enough ammo to fire that weapon in full-auto mode!");
609 } else if (launcher
->altmode
== WP_MODE_BURST
&& obj
->quan
< (objects
[(launcher
->otyp
)].oc_rof
/ 3) ) {
610 pline("You do not have enough ammo to fire that weapon in burst-fire mode!");
616 if ((long)multishot
> obj
->quan
) multishot
= (int)obj
->quan
;
619 if (multishot
< 1) multishot
= 1;
621 if (objects
[obj
->otyp
].oc_skill
== -P_CROSSBOW
&& launcher
&& launcher
->otyp
!= DEMON_CROSSBOW
&& multishot
> 1) multishot
= rnd(multishot
);
623 if (launcher
&& launcher
->oartifact
== ART_DOLORES__WINNING_STRAT
) {
624 if (multishot
> 2) multishot
= 2;
627 if (launcher
&& launcher
->oartifact
== ART_GAT_FROM_HELL
) {
628 int drainhp
= multishot
;
629 while (drainhp
> 0) {
633 if (u
.uhp
> u
.uhpmax
) u
.uhp
= u
.uhpmax
;
636 pline("Unfortunately you didn't have enough health to power this dangerous weapon.");
637 killer_format
= KILLED_BY
;
638 killer
= "firing the gat from hell";
643 pline("%d points of health have been drained!", multishot
);
647 if (launcher
&& launcher
->oartifact
== ART_UPGRADED_LEMURE
) {
648 int verisiertnumber
= multishot
* 100;
649 u
.uprops
[VERISIERTEFFECT
].intrinsic
+= verisiertnumber
;
652 if (launcher
&& launcher
->oartifact
== ART_POST_OFFICE_COURSE
) {
653 int postofficenumber
= multishot
;
654 adjalign(-postofficenumber
);
655 u
.alignlim
-= postofficenumber
;
658 if (launcher
&& (launcher
->otyp
== SUBMACHINE_GUN
|| launcher
->otyp
== LEAD_UNLOADER
|| launcher
->otyp
== ASSAULT_RIFLE
|| launcher
->otyp
== STORM_RIFLE
|| launcher
->otyp
== KALASHNIKOV
|| launcher
->otyp
== AUTO_SHOTGUN
) && launcher
->altmode
== WP_MODE_AUTO
&& !bulletator_allowed(1)) {
659 if (launcher
->otyp
== SUBMACHINE_GUN
) {
660 u
.bulletatorwantedlevel
+= 1;
661 u
.bulletatortimer
+= 100;
662 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 300;
664 if (launcher
->otyp
== LEAD_UNLOADER
) {
665 u
.bulletatorwantedlevel
+= 1;
666 u
.bulletatortimer
+= 100;
667 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 300;
669 if (launcher
->otyp
== ASSAULT_RIFLE
) {
670 u
.bulletatorwantedlevel
+= 3;
671 u
.bulletatortimer
+= 300;
672 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 1000;
674 if (launcher
->otyp
== STORM_RIFLE
) {
675 u
.bulletatorwantedlevel
+= 3;
676 u
.bulletatortimer
+= 300;
677 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 1000;
679 if (launcher
->otyp
== AUTO_SHOTGUN
) {
680 u
.bulletatorwantedlevel
+= 1;
681 u
.bulletatortimer
+= 100;
682 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 1000;
684 if (launcher
->otyp
== KALASHNIKOV
) {
685 u
.bulletatorwantedlevel
+= 4;
686 u
.bulletatortimer
+= 400;
687 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 2000;
689 if (!u
.bulletatorgun
) {
690 pline("You're not allowed to use automatic firearms. Bulletators have been alerted.");
691 u
.bulletatorgun
= TRUE
;
694 if (launcher
&& (launcher
->otyp
== ARM_BLASTER
|| launcher
->otyp
== HEAVY_MACHINE_GUN
|| launcher
->otyp
== BFG
) && !bulletator_allowed(1)) {
695 if (launcher
->otyp
== ARM_BLASTER
) {
696 u
.bulletatorwantedlevel
+= 5;
697 u
.bulletatortimer
+= 500;
698 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 1500;
700 if (launcher
->otyp
== HEAVY_MACHINE_GUN
) {
701 u
.bulletatorwantedlevel
+= 10;
702 u
.bulletatortimer
+= 1000;
703 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 5000;
705 if (launcher
->otyp
== BFG
) {
706 u
.bulletatorwantedlevel
+= 10;
707 u
.bulletatortimer
+= 1000;
708 if (P_MAX_SKILL(P_FIREARM
) == P_ISRESTRICTED
&& P_MAX_SKILL(P_GUN_CONTROL
) == P_ISRESTRICTED
) u
.bulletatortimer
+= 5000;
710 if (!u
.bulletatorgun
) {
711 pline("You're not allowed to use automatic firearms. Bulletators have been alerted.");
712 u
.bulletatorgun
= TRUE
;
715 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& launcher
->altmode
== WP_MODE_AUTO
&& !bulletator_allowed(3)) {
717 u
.bulletatorwantedlevel
+= 1;
718 u
.bulletatortimer
+= 100;
720 if (!u
.bulletatorxbow
) {
721 pline("You're not allowed to use the demon crossbow. Bulletators have been alerted.");
722 u
.bulletatorxbow
= TRUE
;
725 if (launcher
&& launcher
->otyp
== HYDRA_BOW
&& !bulletator_allowed(2)) {
727 u
.bulletatorwantedlevel
+= 1;
728 u
.bulletatortimer
+= 100;
730 if (!u
.bulletatorbow
) {
731 pline("You're not allowed to use the hydra bow. Bulletators have been alerted.");
732 u
.bulletatorbow
= TRUE
;
736 if (launcher
&& launcher
->otyp
== CATAPULT
&& !bulletator_allowed(4)) {
738 u
.bulletatorwantedlevel
+= 1;
739 u
.bulletatortimer
+= 100;
741 if (!u
.bulletatorsling
) {
742 pline("You're not allowed to use the catapult. Bulletators have been alerted.");
743 u
.bulletatorsling
= TRUE
;
747 if (obj
&& obj
->otyp
== FLAMETHROWER
&& !bulletator_allowed(5)) {
749 u
.bulletatorwantedlevel
+= 1;
750 u
.bulletatortimer
+= 100;
752 if (!u
.bulletatorjavelin
) {
753 pline("You're not allowed to use the flamethrower. Bulletators have been alerted.");
754 u
.bulletatorjavelin
= TRUE
;
758 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& !rn2(100)) {
760 register struct permonst
*ptrZ
;
762 if (Aggravate_monster
) {
764 reset_rndmonst(NON_PM
);
771 if (attempts
&& (attempts
% 10000 == 0)) u
.mondiffhack
++;
772 if (!rn2(2000)) reset_rndmonst(NON_PM
);
774 } while ( (!ptrZ
|| (ptrZ
&& !is_demon(ptrZ
))) && attempts
< 50000);
776 if (ptrZ
&& is_demon(ptrZ
)) {
777 (void) makemon(ptrZ
, u
.ux
, u
.uy
, MM_ANGRY
|MM_FRENZIED
);
778 pline("A demon suddenly appears from nowhere!");
779 } else if (rn2(50)) {
788 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& !rn2(100)) {
791 boolean canbeinawall
= FALSE
;
792 if (!rn2(Passes_walls
? 5 : 25)) canbeinawall
= TRUE
;
794 for (tryct
= 0; tryct
< 2000; tryct
++) {
798 if (isok(x
, y
) && ((levl
[x
][y
].typ
> DBWALL
) || canbeinawall
) && !(t_at(x
, y
)) ) {
799 (void) maketrap(x
, y
, rndtrap(), 100, FALSE
);
806 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& !rn2(100)) {
808 pline_The("demon crossbow malfunctioned!");
812 /* nerf multishot --Amy */
814 if (!reallyfullmultishot
) fullmultishot
= 0;
815 if (tech_inuse(T_FLURRY
) && rn2(3)) fullmultishot
= 1;
816 if (tech_inuse(T_DOUBLE_THROWNAGE
) && rn2(3)) fullmultishot
= 1;
818 if (!(PlayerCannotUseSkills
)) {
820 switch (P_SKILL(P_MISSILE_WEAPONS
)) {
822 case P_SKILLED
: if (!rn2(8)) fullmultishot
= 1; break;
823 case P_EXPERT
: if (!rn2(6)) fullmultishot
= 1; break;
824 case P_MASTER
: if (!rn2(4)) fullmultishot
= 1; break;
825 case P_GRAND_MASTER
: if (!rn2(2)) fullmultishot
= 1; break;
826 case P_SUPREME_MASTER
: fullmultishot
= 1; break;
830 if ((multishot
> 3) && !fullmultishot
&& !(launcher
&& launcher
->oartifact
== ART_STREAMSHOOTER
) && !(objects
[obj
->otyp
].oc_skill
== -P_FIREARM
) && !(objects
[obj
->otyp
].oc_skill
== P_FIREARM
) ) multishot
= 2 + rno(multishot
- 2);
832 if (multishot
> 1 && isfriday
&& !rn2(3)) multishot
= rnd(multishot
);
834 if (obj
&& obj
->otyp
== JUMPING_FLAMER
) multishot
= 1;
835 if (launcher
&& launcher
->oartifact
== ART_TSCHUEUU
) multishot
= 1;
837 m_shot
.s
= (ammo_and_launcher(obj
, uwep
) && !(uwep
&& uwep
->otyp
== LASERXBOW
&& !uwep
->lamplit
) && !(uwep
&& uwep
->otyp
== KLIUSLING
&& !uwep
->lamplit
) ) ? TRUE
: FALSE
;
838 /* give a message if shooting more than one, or if player
839 attempted to specify a count */
840 if (multishot
> 1 || shotlimit
> 0) {
841 /* "You shoot N arrows." or "You throw N daggers." */
843 m_shot
.s
? "shoot" : "throw",
844 multishot
, /* (might be 1 if player gave shotlimit) */
845 (multishot
== 1) ? singular(obj
, xname
) : xname(obj
));
848 if (obj
&& obj
->oartifact
== ART_POWERED_BY_HUNGER
) {
849 morehungry(multishot
* 50);
852 if (obj
&& uwep
&& ammo_and_launcher(obj
,uwep
) && uwep
->oartifact
== ART_BUG_BAZOOKA
) {
853 (void) makemon(mkclass(S_XAN
,0), 0, 0, MM_ANGRY
);
854 (void) makemon(mkclass(S_ANT
,0), 0, 0, MM_ANGRY
);
857 if (launcher
&& launcher
->oartifact
== ART_TSCHUEUU
) youmonst
.movement
+= 6;
859 if (launcher
&& launcher
->oartifact
== ART_NOZZLE_CHANGE
) {
860 if (launcher
->altmode
== WP_MODE_AUTO
) launcher
->altmode
= WP_MODE_SINGLE
;
861 else launcher
->altmode
= WP_MODE_AUTO
;
865 if (launcher
&& launcher
->oartifact
== ART_SHENA_S_PANTY
&& !rn2(100)) {
866 TimeStopped
+= rn1(2,2);
867 pline((Role_if(PM_SAMURAI
) || Role_if(PM_NINJA
)) ? "Jikan ga teishi shimashita." : "Time has stopped.");
870 if (launcher
&& launcher
->oartifact
== ART_SCENTFUL_PANTY
&& !rn2(100)) {
871 TimeStopped
+= rn1(2,2);
872 pline((Role_if(PM_SAMURAI
) || Role_if(PM_NINJA
)) ? "Jikan ga teishi shimashita." : "Time has stopped.");
875 if (launcher
&& launcher
->oartifact
== ART_SPEW_THE_BOW
) {
876 buzz(10, rnd(4), u
.ux
, u
.uy
, u
.dx
, u
.dy
);
879 if (tech_inuse(T_GREEN_MISSILE
) && obj
&& obj
->oclass
== VENOM_CLASS
) {
880 int melteestrength
= 1;
881 if (techlevX(get_tech_no(T_GREEN_MISSILE
)) > 9) melteestrength
+= (techlevX(get_tech_no(T_GREEN_MISSILE
)) / 10);
882 buzz(16, melteestrength
, u
.ux
, u
.uy
, u
.dx
, u
.dy
);
885 if (obj
&& obj
->oartifact
== ART_ACTUAL_FLAME
&& u
.uen
>= 5) {
888 buzz(1, 1, u
.ux
, u
.uy
, u
.dx
, u
.dy
); /* 1, not 11, or it'll explode! */
891 if (tech_inuse(T_BLADE_ANGER
) && (objects
[obj
->otyp
].oc_skill
== -P_SHURIKEN
|| objects
[obj
->otyp
].oc_skill
== P_SHURIKEN
) ) {
893 pseudo
= mksobj(SPE_BLADE_ANGER
, FALSE
, 2, FALSE
);
894 if (!pseudo
) goto bladeangerdone
;
895 if (pseudo
->otyp
== GOLD_PIECE
) pseudo
->otyp
= SPE_BLADE_ANGER
; /* minimalist fix */
896 pseudo
->blessed
= pseudo
->cursed
= 0;
897 pseudo
->quan
= 20L; /* do not let useup get it */
898 pseudo
->spe
= obj
->spe
;
899 angeramount
= multishot
;
901 /* we have to clone the entire remaining function because of eternal bugs...
902 * defining pseudo in the function leads to obfree throwing an error if you didn't use blade anger,
903 * and pseudo isn't used in any other way (yet), so let's do it like this --Amy */
905 wep_mask
= obj
->owornmask
;
906 m_shot
.o
= obj
->otyp
;
907 m_shot
.n
= multishot
;
908 for (m_shot
.i
= 1; m_shot
.i
<= m_shot
.n
; m_shot
.i
++) {
910 /* split this object off from its slot if necessary */
911 if (obj
->quan
> 1L) {
912 otmp
= splitobj(obj
, 1L);
916 remove_worn_item(otmp
, FALSE
);
919 throwit(otmp
, wep_mask
, twoweap
, thrown
);
921 m_shot
.n
= m_shot
.i
= 0;
922 m_shot
.o
= STRANGE_OBJECT
;
925 /* now do blade anger damage (it usually has a higher range than the thrown shuriken) */
926 if (u
.uen
< 10) pline("Not enough mana for blade anger.");
927 while (pseudo
&& angeramount
>= 1) {
935 if (pseudo
) obfree(pseudo
, (struct obj
*)0); /* now, get rid of it */
940 if ((tech_inuse(T_BEAMSWORD
) || (obj
&& obj
->oartifact
== ART_LINK_S_MASTER_SWORD
)) && is_lightsaber(obj
) && obj
->lamplit
) {
941 if (obj
&& obj
->oartifact
== ART_LINK_S_MASTER_SWORD
) u
.linkmasterswordhack
= 1;
943 pseudo
= mksobj(SPE_BEAMSWORD
, FALSE
, 2, FALSE
);
944 if (!pseudo
) goto bladeangerdone
;
945 if (pseudo
->otyp
== GOLD_PIECE
) pseudo
->otyp
= SPE_BEAMSWORD
; /* minimalist fix */
946 pseudo
->blessed
= pseudo
->cursed
= 0;
947 pseudo
->quan
= 20L; /* do not let useup get it */
948 pseudo
->spe
= obj
->spe
;
950 /* we have to clone the entire remaining function because of eternal bugs...
951 * defining pseudo in the function leads to obfree throwing an error if you didn't use blade anger,
952 * and pseudo isn't used in any other way (yet), so let's do it like this --Amy */
954 wep_mask
= obj
->owornmask
;
955 m_shot
.o
= obj
->otyp
;
956 m_shot
.n
= multishot
;
957 for (m_shot
.i
= 1; m_shot
.i
<= m_shot
.n
; m_shot
.i
++) {
959 /* split this object off from its slot if necessary */
960 if (obj
->quan
> 1L) {
961 otmp
= splitobj(obj
, 1L);
965 remove_worn_item(otmp
, FALSE
);
968 throwit(otmp
, wep_mask
, twoweap
, thrown
);
970 m_shot
.n
= m_shot
.i
= 0;
971 m_shot
.o
= STRANGE_OBJECT
;
974 /* now do beamsword damage (it usually has a higher range than the thrown lightsaber) */
977 if (pseudo
) obfree(pseudo
, (struct obj
*)0); /* now, get rid of it */
984 wep_mask
= obj
->owornmask
;
985 m_shot
.o
= obj
->otyp
;
986 m_shot
.n
= multishot
;
987 for (m_shot
.i
= 1; m_shot
.i
<= m_shot
.n
; m_shot
.i
++) {
991 if (!(PlayerCannotUseSkills
)) {
992 switch (P_SKILL(P_MISSILE_WEAPONS
)) {
994 case P_BASIC
: savechance
= 1; break;
995 case P_SKILLED
: savechance
= 2; break;
996 case P_EXPERT
: savechance
= 3; break;
997 case P_MASTER
: savechance
= 4; break;
998 case P_GRAND_MASTER
:savechance
= 5; break;
999 case P_SUPREME_MASTER
:savechance
= 6; break;
1000 default: savechance
+= 0; break;
1004 if (!obj
) { /* uh-oh */
1005 You("suddenly ran out of ammo for your ranged attack!");
1006 m_shot
.n
= m_shot
.i
= 0;
1007 m_shot
.o
= STRANGE_OBJECT
;
1012 /* melee weapons dull when used repeatedly, so firing a launcher should do the same --Amy */
1013 if (uwep
&& ammo_and_launcher(obj
, uwep
) && weaponwilldull(uwep
) && (rnd(7) > savechance
) && !issoviet
) {
1014 if (uwep
->greased
) {
1016 pline("Your weapon loses its grease.");
1019 pline("Your weapon dulls.");
1023 if (uswapwep
&& ammo_and_launcher(obj
, uswapwep
) && weaponwilldull(uswapwep
) && (rnd(7) > savechance
) && !issoviet
) {
1024 if (uswapwep
->greased
) {
1025 uswapwep
->greased
--;
1026 pline("Your weapon loses its grease.");
1029 pline("Your weapon dulls.");
1034 if (uwep
&& uwep
->oartifact
== ART_LOUD_SHITTER
&& ammo_and_launcher(obj
, uwep
)) {
1037 if (uswapwep
&& uswapwep
->oartifact
== ART_LOUD_SHITTER
&& ammo_and_launcher(obj
, uswapwep
)) {
1041 twoweap
= u
.twoweap
;
1042 /* split this object off from its slot if necessary */
1043 if (obj
->quan
> 1L) {
1044 otmp
= splitobj(obj
, 1L);
1047 if (otmp
->owornmask
)
1048 remove_worn_item(otmp
, FALSE
);
1051 throwit(otmp
, wep_mask
, twoweap
, thrown
);
1052 if (autismweaponcheck(ART_PSG
) || autismweaponcheck(ART_BORKED_PARA
)) {
1056 m_shot
.n
= m_shot
.i
= 0;
1057 m_shot
.o
= STRANGE_OBJECT
;
1068 register struct obj
*obj
;
1069 int oldmulti
= multi
, result
, shotlimit
;
1070 char *oldsave_cm
= save_cm
;
1074 * Since some characters shoot multiple missiles at one time,
1075 * allow user to specify a count prefix for 'f' or or select
1076 * a number of items in the item selection for 't' to limit
1077 * number of items thrown (to avoid possibly hitting something
1078 * behind target after killing it, or perhaps to conserve ammo).
1080 * Nethack 3.3.0 uses prefixes for all - should this revert to that?
1082 * Prior to 3.3.0, command ``3t'' meant ``t(shoot) t(shoot) t(shoot)''
1083 * and took 3 turns. Now it means ``t(shoot at most 3 missiles)''.
1086 if (trap
= t_at(u
.ux
, u
.uy
)) {
1087 if (trap
->ttyp
== VIVISECTION_TRAP
) {
1088 You("are in vivisection, and therefore unable to use a ranged attack!");
1089 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1094 if (u
.rangedreload
) {
1095 You("have to reload, which is gonna take %d more turns!", u
.rangedreload
);
1096 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1100 if (u
.twoweap
&& uarms
) {
1101 You("are way too busy with your two weapons and shield.");
1102 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1106 if (notake(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) ) {
1107 You("are physically incapable of throwing anything.");
1108 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1110 if (yn("But you can try to throw anyway. Okay?") == 'y') {
1111 if (rn2(3) && !polyskillchance()) {
1113 pline("The darn thing doesn't seem to fly very far.");
1114 if (!rn2(20)) badeffect();
1115 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1122 if(check_capacity((char *)0)) return(0);
1123 obj
= getobj(uslinging() ? bullets
: toss_objs
, "throw");
1124 /* it is also possible to throw food */
1125 /* (or jewels, or iron balls... ) */
1127 if (!obj
) return(0);
1130 if (obj
->otyp
== SCR_MAIL
) {
1131 You("try to cheat, but it fails.");
1132 if (Is_airlevel(&u
.uz
)) pline("Stop being a wiseguy and play the game properly already! :-P");
1137 if (EpviProblemActive
&& obj
&& (objects
[obj
->otyp
].oc_minlvl
> (u
.ulevel
+ u
.xtralevelmult
- 1) ) ) {
1138 verbalize("I cannot use that yet.");
1142 /* kludge to work around parse()'s pre-decrement of 'multi' */
1143 shotlimit
= (multi
|| save_cm
) ? multi
+ 1 : 0;
1145 result
= throw_obj(obj
, shotlimit
, THROW_UWEP
);
1148 * [ALI] Bug fix: Temporary paralysis (eg., from hurtle) cancels
1149 * any count for the throw command.
1153 save_cm
= oldsave_cm
;
1158 /* KMH -- automatically fill quiver */
1159 /* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
1163 struct obj
*otmp
, *oammo
= 0, *omissile
= 0, *omisc
= 0, *altammo
= 0;
1168 /* Scan through the inventory */
1169 for (otmp
= invent
; otmp
; otmp
= otmp
->nobj
) {
1170 if (otmp
->owornmask
|| otmp
->oartifact
|| !otmp
->dknown
) {
1172 } else if (otmp
->otyp
== ROCK
||
1173 /* seen rocks or known flint or known glass */
1174 (objects
[otmp
->otyp
].oc_name_known
&&
1175 otmp
->otyp
== FLINT
) ||
1176 (objects
[otmp
->otyp
].oc_name_known
&&
1177 otmp
->oclass
== GEM_CLASS
&&
1178 objects
[otmp
->otyp
].oc_material
== MT_GLASS
)) {
1181 else if (ammo_and_launcher(otmp
, uswapwep
))
1185 } else if (otmp
->oclass
== GEM_CLASS
) {
1186 ; /* skip non-rock gems--they're ammo but
1187 player has to select them explicitly */
1188 } else if (is_ammo(otmp
)) {
1189 if (ammo_and_launcher(otmp
, uwep
))
1190 /* Ammo matched with launcher (bow and arrow, crossbow and bolt) */
1192 else if (ammo_and_launcher(otmp
, uswapwep
))
1195 /* Mismatched ammo (no better than an ordinary weapon) */
1197 } else if (is_missile(otmp
)) {
1198 /* Missile (dart, shuriken, etc.) */
1200 } else if (otmp
->oclass
== WEAPON_CLASS
&& throwing_weapon(otmp
)) {
1201 /* Ordinary weapon */
1202 if (objects
[otmp
->otyp
].oc_skill
== P_DAGGER
1210 /* Pick the best choice */
1226 int result
, shotlimit
;
1229 if (trap
= t_at(u
.ux
, u
.uy
)) {
1230 if (trap
->ttyp
== VIVISECTION_TRAP
) {
1231 You("are in vivisection, and therefore unable to use a ranged attack!");
1232 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1237 if (u
.twoweap
&& uarms
) {
1238 You("are way too busy with your two weapons and shield.");
1239 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1243 if (u
.rangedreload
) {
1244 You("have to reload, which is gonna take %d more turns!", u
.rangedreload
);
1245 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1249 if (notake(youmonst
.data
) && !Race_if(PM_TRANSFORMER
) ) {
1250 You("are physically incapable of doing that.");
1251 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1253 if (yn("But you can try to fire anyway. Okay?") == 'y') {
1254 if (rn2(3) && !polyskillchance()) {
1256 pline("The darn thing doesn't seem to fly very far.");
1257 if (!rn2(20)) badeffect();
1258 if (flags
.moreforced
&& !MessagesSuppressed
) display_nhwindow(WIN_MESSAGE
, TRUE
); /* --More-- */
1266 if (uquiver
&& uquiver
->otyp
== SCR_MAIL
) {
1267 You("try to cheat, but it fails.");
1268 if (Is_airlevel(&u
.uz
)) pline("Stop being a wiseguy and play the game properly already! :-P");
1273 if (EpviProblemActive
&& uquiver
&& (objects
[uquiver
->otyp
].oc_minlvl
> (u
.ulevel
+ u
.xtralevelmult
- 1) ) ) {
1274 verbalize("I cannot use that yet.");
1278 if(check_capacity((char *)0)) return(0);
1280 if (!flags
.autoquiver
) {
1281 /* Don't automatically fill the quiver */
1282 You("have no ammunition readied!");
1283 if (iflags
.quiver_fired
)
1284 dowieldquiver(); /* quiver_fired */
1288 else { /* quiver_fired */
1291 You("have nothing appropriate for your quiver!");
1294 You("fill your quiver:");
1295 prinv((char *)0, uquiver
, 0L);
1297 } /* quiver_fired */
1301 * Since some characters shoot multiple missiles at one time,
1302 * allow user to specify a count prefix for 'f' or 't' to limit
1303 * number of items thrown (to avoid possibly hitting something
1304 * behind target after killing it, or perhaps to conserve ammo).
1306 * The number specified can never increase the number of missiles.
1307 * Using ``5f'' when the shooting skill (plus RNG) dictates launch
1308 * of 3 projectiles will result in 3 being shot, not 5.
1310 /* kludge to work around parse()'s pre-decrement of `multi' */
1311 shotlimit
= (multi
|| save_cm
) ? multi
+ 1 : 0;
1312 multi
= 0; /* reset; it's been used up */
1315 if (!can_twoweapon()) untwoweapon();
1316 else if (ammo_and_launcher(uquiver
,uwep
)
1317 && ammo_and_launcher(uquiver
, uswapwep
)){
1318 result
= throw_obj(uquiver
, shotlimit
, THROW_UWEP
);
1319 if ((result
== 1) && uquiver
)
1320 result
+= throw_obj(uquiver
, shotlimit
, THROW_USWAPWEP
);
1321 if (result
> 1) result
--;
1325 result
= (throw_obj(uquiver
, shotlimit
, THROW_UWEP
));
1332 * Object hits floor at hero's feet. Called from drop() and throwit().
1336 register struct obj
*obj
;
1338 if (IS_SOFT(levl
[u
.ux
][u
.uy
].typ
) || u
.uinwater
) {
1342 if (IS_ALTAR(levl
[u
.ux
][u
.uy
].typ
))
1345 pline("%s hit%s the %s.", Doname2(obj
),
1346 (obj
->quan
== 1L) ? "s" : "", surface(u
.ux
,u
.uy
));
1347 /* waaaaaaaaaaay too big a penalty to lose ALL potions unconditionally --Amy */
1348 if (!rn2(obj
->oerodeproof
? 100 : 20)) {
1349 if (hero_breaks(obj
, u
.ux
, u
.uy
, TRUE
)) return;
1351 if (ship_object(obj
, u
.ux
, u
.uy
, FALSE
)) return;
1353 if (!u
.uswallow
) container_impact_dmg(obj
);
1357 * Walk a path from src_cc to dest_cc, calling a proc for each location
1358 * except the starting one. If the proc returns FALSE, stop walking
1359 * and return FALSE. If stopped early, dest_cc will be the location
1360 * before the failed callback.
1363 walk_path(src_cc
, dest_cc
, check_proc
, arg
)
1366 boolean (*check_proc
)(void *, int, int);
1369 int x
, y
, dx
, dy
, x_change
, y_change
, err
, i
, prev_x
, prev_y
;
1370 boolean keep_going
= TRUE
;
1372 /* Use Bresenham's Line Algorithm to walk from src to dest */
1373 dx
= dest_cc
->x
- src_cc
->x
;
1374 dy
= dest_cc
->y
- src_cc
->y
;
1375 prev_x
= x
= src_cc
->x
;
1376 prev_y
= y
= src_cc
->y
;
1400 /* check for early exit condition */
1401 if (!(keep_going
= (*check_proc
)(arg
, x
, y
)))
1414 /* check for early exit condition */
1415 if (!(keep_going
= (*check_proc
)(arg
, x
, y
)))
1421 return TRUE
; /* successful */
1423 dest_cc
->x
= prev_x
;
1424 dest_cc
->y
= prev_y
;
1429 * Single step for the hero flying through the air from jumping, flying,
1430 * etc. Called from hurtle() and jump() via walk_path(). We expect the
1431 * argument to be a pointer to an integer -- the range -- which is
1432 * used in the calculation of points off if we hit something.
1434 * Bumping into monsters won't cause damage but will wake them and make
1435 * them angry. Auto-pickup isn't done, since you don't have control over
1436 * your movements at the time.
1438 * Possible additions/changes:
1439 * o really attack monster if we hit one
1440 * o set stunned if we hit a wall or door
1441 * o reset nomul when we stop
1442 * o creepy feeling if pass through monster (if ever implemented...)
1443 * o bounce off walls
1444 * o let jumps go over boulders
1447 hurtle_step(arg
, x
, y
)
1451 int ox
, oy
, *range
= (int *)arg
;
1454 boolean may_pass
= TRUE
;
1458 You_feel("the spirits holding you back.");
1460 } else if (!in_out_region(x
, y
)) {
1462 } else if (*range
== 0) {
1463 return FALSE
; /* previous step wants to stop now */
1466 if (!Passes_walls
|| !(may_pass
= may_passwall(x
, y
))) {
1467 if (IS_ROCK(levl
[x
][y
].typ
) || closed_door(x
,y
)) {
1471 if (IS_TREE(levl
[x
][y
].typ
))
1472 s
= "bumping into a tree";
1473 else if (IS_ROCK(levl
[x
][y
].typ
))
1474 s
= "bumping into a wall";
1476 s
= "bumping into a door";
1477 losehp(rnd(2+*range
), s
, KILLED_BY
);
1480 if (levl
[x
][y
].typ
== IRONBARS
) {
1481 You("crash into some iron bars. Ouch!");
1482 losehp(rnd(2+*range
), "crashing into iron bars", KILLED_BY
);
1485 if ((obj
= sobj_at(BOULDER
,x
,y
)) != 0) {
1486 You("bump into a %s. Ouch!", xname(obj
));
1487 losehp(rnd(2+*range
), "bumping into a boulder", KILLED_BY
);
1491 /* did we hit a no-dig non-wall position? */
1492 You("smack into something!");
1493 losehp(rnd(2+*range
), "touching the edge of the universe", KILLED_BY
);
1496 if ((u
.ux
- x
) && (u
.uy
- y
) &&
1497 bad_rock(&youmonst
,u
.ux
,y
) && bad_rock(&youmonst
,x
,u
.uy
)) {
1498 boolean too_much
= (invent
&& (inv_weight() + weight_cap() > 5000));
1499 /* Move at a diagonal. */
1500 if (bigmonst(youmonst
.data
) || too_much
) {
1501 You("%sget forcefully wedged into a crevice.",
1502 too_much
? "and all your belongings " : "");
1503 losehp(rnd(2+*range
), "wedging into a narrow crevice", KILLED_BY
);
1509 if ((mon
= m_at(x
, y
)) != 0) {
1510 You("bump into %s.", a_monnam(mon
));
1514 if ((u
.ux
- x
) && (u
.uy
- y
) &&
1515 bad_rock(&youmonst
, u
.ux
, y
) && bad_rock(&youmonst
, x
, u
.uy
)) {
1516 /* Move at a diagonal. */
1517 if (In_sokoban(&u
.uz
)) {
1518 You("come to an abrupt halt!");
1527 newsym(ox
, oy
); /* update old position */
1528 vision_recalc(1); /* update for new position */
1531 * Each trap should really trigger on the recoil if
1532 * it would trigger during normal movement. However,
1533 * not all the possible side-effects of this are
1534 * tested [as of 3.4.0] so we trigger those that
1535 * we have tested, and offer a message for the
1536 * ones that we have not yet tested.
1538 if ((ttmp
= t_at(x
, y
)) != 0) {
1539 if (ttmp
->ttyp
== MAGIC_PORTAL
) {
1542 } else if (ttmp
->ttyp
== FIRE_TRAP
) {
1544 } else if ((ttmp
->ttyp
== PIT
|| ttmp
->ttyp
== SPIKED_PIT
|| ttmp
->ttyp
== GIANT_CHASM
|| ttmp
->ttyp
== SHIT_PIT
|| ttmp
->ttyp
== MANA_PIT
|| ttmp
->ttyp
== ANOXIC_PIT
|| ttmp
->ttyp
== HYPOXIC_PIT
|| ttmp
->ttyp
== ACID_PIT
|| ttmp
->ttyp
== SHAFT_TRAP
|| ttmp
->ttyp
== CURRENT_SHAFT
||
1545 ttmp
->ttyp
== HOLE
|| ttmp
->ttyp
== TRAPDOOR
) &&
1546 In_sokoban(&u
.uz
)) {
1547 /* Air currents overcome the recoil */
1553 You("pass right over %s %s.",
1554 (ttmp
->ttyp
== ARROW_TRAP
) ? "an" : "a",
1555 defsyms
[trap_to_defsym(ttmp
->ttyp
)].explanation
);
1558 if (--*range
< 0) /* make sure our range never goes negative */
1566 mhurtle_step(arg
, x
, y
)
1570 struct monst
*mon
= (struct monst
*)arg
;
1572 /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
1573 * rather than just stopping before.
1575 if (goodpos(x
, y
, mon
, 0) && m_in_out_region(mon
, x
, y
)) {
1576 remove_monster(mon
->mx
, mon
->my
);
1577 newsym(mon
->mx
, mon
->my
);
1578 place_monster(mon
, x
, y
);
1579 newsym(mon
->mx
, mon
->my
);
1581 (void) mintrap(mon
);
1588 * The player moves through the air for a few squares as a result of
1589 * throwing or kicking something.
1591 * dx and dy should be the direction of the hurtle, not of the original
1592 * kick or throw and be only.
1595 hurtle(dx
, dy
, range
, verbose
)
1601 /* The chain is stretched vertically, so you shouldn't be able to move
1602 * very far diagonally. The premise that you should be able to move one
1603 * spot leads to calculations that allow you to only move one spot away
1604 * from the ball, if you are levitating over the ball, or one spot
1605 * towards the ball, if you are at the end of the chain. Rather than
1606 * bother with all of that, assume that there is no slack in the chain
1607 * for diagonal movement, give the player a message and return.
1609 if(Punished
&& !carried(uball
)) {
1610 You_feel("a tug from the iron ball.");
1613 } else if (u
.utrap
) {
1614 You("are anchored by the %s.",
1615 u
.utraptype
== TT_WEB
? "web" : u
.utraptype
== TT_GLUE
? "glue" : u
.utraptype
== TT_LAVA
? "lava" :
1616 u
.utraptype
== TT_INFLOOR
? surface(u
.ux
,u
.uy
) : "trap");
1621 /* make sure dx and dy are [-1,0,1] */
1625 if(!range
|| (!dx
&& !dy
) || u
.ustuck
) return; /* paranoia */
1627 nomul(-range
, "moving through the air", TRUE
);
1630 You("%s in the opposite direction.", range
> 1 ? "hurtle" : "float");
1631 /* if we're in the midst of shooting multiple projectiles, stop */
1632 if (m_shot
.i
< m_shot
.n
) {
1633 /* last message before hurtling was "you shoot N arrows" */
1634 You("stop %sing after the first %s.",
1635 m_shot
.s
? "shoot" : "throw", m_shot
.s
? "shot" : "toss");
1636 m_shot
.n
= m_shot
.i
; /* make current shot be the last */
1639 /* This used to give sokoban penalties but you can't actually bypass anything so the penalty is removed --Amy */
1640 /* Soviet Russia comment is in apply.c */
1642 if (issoviet
&& In_sokoban(&u
.uz
)) {
1644 pline("Teper' vy teryayete ochko udachi KHAR KHAR. Eto deystviye ne pomoglo vam reshit' golovolomki, no my takiye elitnyye.");
1645 if (evilfriday
) u
.ugangr
++;
1650 /* this setting of cc is only correct if dx and dy are [-1,0,1] only */
1651 cc
.x
= u
.ux
+ (dx
* range
);
1652 cc
.y
= u
.uy
+ (dy
* range
);
1653 (void) walk_path(&uc
, &cc
, hurtle_step
, (void *)&range
);
1654 teleds(cc
.x
, cc
.y
, FALSE
);
1657 /* Move a monster through the air for a few squares.
1660 mhurtle(mon
, dx
, dy
, range
)
1666 /* At the very least, debilitate the monster */
1670 /* Is the monster stuck or too heavy to push?
1671 * (very large monsters have too much inertia, even floaters and flyers)
1673 if (mon
->data
->msize
>= MZ_HUGE
|| mon
== u
.ustuck
|| mon
->mtrapped
)
1676 /* Make sure dx and dy are [-1,0,1] */
1679 if(!range
|| (!dx
&& !dy
)) return; /* paranoia */
1681 /* Send the monster along the path */
1684 cc
.x
= mon
->mx
+ (dx
* range
);
1685 cc
.y
= mon
->my
+ (dy
* range
);
1686 (void) walk_path(&mc
, &cc
, mhurtle_step
, (void *)mon
);
1691 check_shop_obj(obj
, x
, y
, broken
)
1692 register struct obj
*obj
;
1693 register xchar x
, y
;
1694 register boolean broken
;
1696 struct monst
*shkp
= shop_keeper(*u
.ushops
);
1702 (void)stolen_value(obj
, u
.ux
, u
.uy
,
1703 (boolean
)shkp
->mpeaceful
, FALSE
, TRUE
);
1704 subfrombill(obj
, shkp
);
1710 if (!costly_spot(x
, y
) || *in_rooms(x
, y
, SHOPBASE
) != *u
.ushops
) {
1711 /* thrown out of a shop or into a different shop */
1713 (void)stolen_value(obj
, u
.ux
, u
.uy
,
1714 (boolean
)shkp
->mpeaceful
, FALSE
, FALSE
);
1715 subfrombill(obj
, shkp
);
1718 if (costly_spot(u
.ux
, u
.uy
) && costly_spot(x
, y
)) {
1719 if(obj
->unpaid
) subfrombill(obj
, shkp
);
1720 else if(!(x
== shkp
->mx
&& y
== shkp
->my
))
1727 * Hero tosses an object upwards with appropriate consequences.
1729 * Returns FALSE if the object is gone.
1732 toss_up(obj
, hitsroof
)
1737 /* note: obj->quan == 1 */
1740 if (breaktest(obj
)) {
1741 pline("%s hits the %s.", Doname2(obj
), ceiling(u
.ux
, u
.uy
));
1742 breakmsg(obj
, !Blind
);
1743 if (issegfaulter
&& obj
->otyp
== SEGFAULT_VENOM
&& !rn2(5) ) { /* segfault panic! */
1744 u
.segfaultpanic
= TRUE
;
1745 } else if (obj
->oartifact
== ART_DO_NOT_THROW_ME
) { /* uh-oh... you really messed up big time there. */
1746 u
.segfaultpanic
= TRUE
;
1748 breakobj(obj
, u
.ux
, u
.uy
, TRUE
, TRUE
);
1755 pline("%s%s hits the %s, then falls back on top of your %s.",
1756 Doname2(obj
), almost
, ceiling(u
.ux
,u
.uy
), body_part(HEAD
));
1758 /* object now hits you */
1760 if (obj
->oclass
== POTION_CLASS
) {
1761 potionhit(&youmonst
, obj
, TRUE
);
1762 } else if (breaktest(obj
)) {
1763 int otyp
= obj
->otyp
, ocorpsenm
= obj
->corpsenm
;
1766 /* need to check for blindness result prior to destroying obj */
1767 blindinc
= (otyp
== CREAM_PIE
|| otyp
== BLINDING_VENOM
) &&
1768 /* AT_WEAP is ok here even if attack type was AT_SPIT */
1769 can_blnd(&youmonst
, &youmonst
, AT_WEAP
, obj
) ? rnd(25) : 0;
1771 breakmsg(obj
, !Blind
);
1772 breakobj(obj
, u
.ux
, u
.uy
, TRUE
, TRUE
);
1773 obj
= 0; /* it's now gone */
1775 case PETRIFYIUM_BAR
:
1776 if (!uarmh
&& (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) &&
1777 !(poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
)))
1779 case PETRIFYIUM_BRA
:
1780 if (!uarmh
&& (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) &&
1781 !(poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
)))
1784 if (touch_petrifies(&mons
[ocorpsenm
]) && ocorpsenm
!= PM_PLAYERMON
&&
1785 !uarmh
&& (!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) &&
1786 !(poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
)))
1789 case BLINDING_VENOM
:
1790 pline("You've got it all over your %s!", body_part(FACE
));
1792 if (otyp
== BLINDING_VENOM
&& !Blind
)
1793 pline("It blinds you!");
1794 u
.ucreamed
+= blindinc
;
1795 make_blinded(Blinded
+ (long)blindinc
, FALSE
);
1796 if (!Blind
) Your("%s", vision_clears
);
1803 } else { /* neither potion nor other breaking object */
1804 boolean less_damage
= uarmh
&& is_hardmaterial(uarmh
), artimsg
= FALSE
;
1805 int dmg
= dmgval(obj
, &youmonst
);
1808 /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */
1809 artimsg
= artifact_hit((struct monst
*)0, &youmonst
,
1810 obj
, &dmg
, rn1(18,2));
1812 if (!dmg
) { /* probably wasn't a weapon; base damage on weight */
1813 dmg
= (int) obj
->owt
/ 100;
1814 if (dmg
< 1) dmg
= 1;
1815 else if (dmg
> 6) dmg
= 6;
1816 if (is_shade(youmonst
.data
) && objects
[obj
->otyp
].oc_material
!= MT_SILVER
&& objects
[obj
->otyp
].oc_material
!= MT_ARCANIUM
)
1819 if (dmg
> 1 && less_damage
) dmg
= 1;
1821 if (increase_damage_bonus_value() > 1) dmg
+= rnd(increase_damage_bonus_value());
1822 else dmg
+= increase_damage_bonus_value();
1824 if (dmg
> 0 && uarmh
&& uarmh
->oartifact
== ART_REMOTE_GAMBLE
) dmg
+= 2;
1825 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_MOTHERFUCKER_TROPHY
) dmg
+= 5;
1826 if (dmg
> 0 && u
.tiksrvzllatdown
) dmg
+= 1;
1828 if (dmg
> 0 && (uarmg
&& itemhasappearance(uarmg
, APP_UNCANNY_GLOVES
))) dmg
+= 1;
1829 if (dmg
> 0 && (uarmg
&& itemhasappearance(uarmg
, APP_SLAYING_GLOVES
))) dmg
+= 1;
1831 if (dmg
> 0 && uarmc
&& uarmc
->oartifact
== ART_INA_S_SORROW
&& u
.uhunger
< 0) dmg
+= 3;
1832 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SPAMBAIT_FIRE
) dmg
+= 2;
1833 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_GARY_S_RIVALRY
) dmg
+= 2;
1834 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_KATI_S_IRRESISTIBLE_STILET
) dmg
+= 2;
1835 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_STREET_ROCKZ
) dmg
+= 2;
1836 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_THOR_S_STRIKE
&& ACURR(A_STR
) >= STR19(25)) dmg
+= 5;
1837 if (dmg
> 0 && uarmh
&& uarmh
->oartifact
== ART_IRON_HELM_OF_GORLIM
) dmg
+= 10;
1838 if (dmg
> 0 && uarmh
&& uarmh
->oartifact
== ART_SUDUNSEL
) dmg
+= 2;
1839 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_KLOCKING_NOISE
) dmg
+= 2;
1840 if (dmg
> 0 && uarm
&& uarm
->otyp
== DARK_DRAGON_SCALES
) dmg
+= 1;
1841 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_FLOEMMELFLOEMMELFLOEMMELFL
) dmg
+= 1;
1842 if (dmg
> 0 && uarm
&& uarm
->otyp
== DARK_DRAGON_SCALE_MAIL
) dmg
+= 1;
1843 if (dmg
> 0 && uarms
&& uarms
->otyp
== DARK_DRAGON_SCALE_SHIELD
) dmg
+= 1;
1844 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_YES_TO_RANGED_COMBAT
) dmg
+= rnd(6);
1845 if (dmg
> 0 && uleft
&& uleft
->oartifact
== ART_BLIND_PILOT
) dmg
+= 10;
1846 if (dmg
> 0 && uright
&& uright
->oartifact
== ART_BLIND_PILOT
) dmg
+= 10;
1847 if (dmg
> 0 && uamul
&& uamul
->oartifact
== ART_NOW_YOU_HAVE_LOST
) dmg
+= 10;
1848 if (dmg
> 0 && Role_if(PM_ARCHEOLOGIST
) && uamul
&& uamul
->oartifact
== ART_ARCHEOLOGIST_SONG
) dmg
+= 2;
1849 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_MADELINE_S_STUPID_GIRL
) dmg
+= 3;
1850 if (dmg
> 0 && ublindf
&& ublindf
->oartifact
== ART_EYEHANDER
) dmg
+= 5;
1851 if (dmg
> 0) dmg
+= (Drunken_boxing
&& Confusion
);
1852 if (dmg
> 0) dmg
+= (StrongDrunken_boxing
&& Confusion
);
1853 if (RngeBloodlust
&& dmg
> 0) dmg
++;
1854 if (dmg
> 0 && u
.boosttimer
) dmg
+= 2;
1855 if (dmg
> 0 && uarms
&& uarms
->oartifact
== ART_TEH_BASH_R
) dmg
+= 2;
1856 if (dmg
> 0 && uarmc
&& uarmc
->oartifact
== ART_DUFFDUFFDUFF
) dmg
+= 3;
1857 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_RAAAAAAAARRRRRRGH
) dmg
+= 5;
1858 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_SI_OH_WEE
) dmg
+= 2;
1859 if (dmg
> 0 && powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_RHEA_S_MISSING_EYESIGHT
) dmg
+= rnd(5);
1860 if (dmg
> 0 && powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_SOME_LITTLE_AID
) dmg
+= 1;
1861 if (dmg
> 0 && Race_if(PM_VIKING
)) dmg
+= 1;
1862 if (dmg
> 0 && Race_if(PM_SERB
)) dmg
+= 1;
1863 if (dmg
> 0 && Race_if(PM_RUSMOT
)) dmg
+= 2;
1864 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_MAJOR_PRESENCE
) dmg
+= 2;
1865 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_SNAILHUNT
) dmg
+= 1;
1866 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_MAY_BRITT_S_ADULTHOOD
) dmg
+= 1;
1867 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_CRASHING_YOUR_SISTER_S_WED
) dmg
+= 2;
1868 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 0) dmg
+= 1;
1869 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 49) dmg
+= 1;
1870 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 99) dmg
+= 1;
1871 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 149) dmg
+= 1;
1872 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 199) dmg
+= 1;
1873 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 249) dmg
+= 1;
1874 if (dmg
> 0 && bmwride(ART_KERSTIN_S_COWBOY_BOOST
)) dmg
+= 2;
1875 if (dmg
> 0 && Role_if(PM_OTAKU
) && uarmc
&& itemhasappearance(uarmc
, APP_FOURCHAN_CLOAK
)) dmg
+= 1;
1876 if (dmg
> 0 && Race_if(PM_RODNEYAN
)) dmg
+= (1 + (GushLevel
/ 3) );
1877 if (dmg
> 0 && uarmf
&& uarmf
->oartifact
== ART_PROPERTY_GRUMBLE
) dmg
+= 8;
1878 if (dmg
> 0 && uarmh
&& uarmh
->oartifact
== ART_HABIBA_S_MATRONAGE
) dmg
+= 2;
1879 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_UNKNOWINGNESS_AS_A_WEAPON
&& !(objects
[uarmg
->otyp
].oc_name_known
)) dmg
+= 5;
1880 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_BUCK_SHOT
&& !uwep
->bknown
) dmg
+= 2;
1881 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_FALCO_S_ORB
) dmg
+= 1;
1882 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_PLUS_TO_DAM
) dmg
+= 2;
1883 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_YOU_ARE_UGLY
) dmg
+= 1;
1884 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_THERE_GOES_SHE_TO
) dmg
+= 4;
1885 if (dmg
> 0 && uarms
&& uarms
->oartifact
== ART_RONDITSCH
) dmg
+= 1;
1886 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_NOOBY_BONUS_STYLE
&& !bimanual(uwep
)) dmg
+= 2;
1887 if (dmg
> 0 && powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_NIOBE_S_ANGER
) dmg
+= 2;
1888 if (dmg
> 0 && powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_I_M_GONNA_CRUSH_YA_
) dmg
+= 4;
1889 if (dmg
> 0 && uarms
&& uarms
->oartifact
== ART_UNUSUAL_ENCH
) dmg
+= 1;
1890 if (dmg
> 0 && bmwride(ART_ZIN_BA
)) dmg
+= 1;
1891 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_I_AM_YOUR_FALL
) dmg
+= 2;
1892 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_ETH_ITH
) dmg
+= 3;
1893 if (dmg
> 0 && uleft
&& uleft
->oartifact
== ART_RING_OF_THROR
) dmg
+= 2;
1894 if (dmg
> 0 && uright
&& uright
->oartifact
== ART_RING_OF_THROR
) dmg
+= 2;
1895 if (dmg
> 0 && uleft
&& uleft
->oartifact
== ART_KRATSCHEM_HARD
) dmg
+= 2;
1896 if (dmg
> 0 && uright
&& uright
->oartifact
== ART_KRATSCHEM_HARD
) dmg
+= 2;
1897 if (dmg
> 0 && uleft
&& uleft
->oartifact
== ART_WILDFIST
) dmg
+= 4;
1898 if (dmg
> 0 && uright
&& uright
->oartifact
== ART_WILDFIST
) dmg
+= 4;
1899 if (dmg
> 0 && uarm
&& uarm
->oartifact
== ART_EITHER_INTELLIGENT_OR_FAIR
) dmg
+= 2;
1900 if (dmg
> 0 && uarmg
&& uarmg
->oartifact
== ART_DOCHGOGRAP
) dmg
+= 2;
1902 if (dmg
> 0 && uwep
&& uwep
->oartifact
== ART_AK_____
) {
1903 if (!PlayerCannotUseSkills
) {
1904 if (P_SKILL(P_FIREARM
) < P_BASIC
) dmg
+= 3;
1905 else if (P_SKILL(P_FIREARM
) == P_BASIC
) dmg
+= 2;
1906 else if (P_SKILL(P_FIREARM
) == P_SKILLED
) dmg
+= 1;
1908 if (P_SKILL(P_FIREARM
) == P_MASTER
) dmg
-= 2;
1909 if (P_SKILL(P_FIREARM
) == P_GRAND_MASTER
) dmg
-= 4;
1910 if (P_SKILL(P_FIREARM
) == P_SUPREME_MASTER
) dmg
-= 6;
1912 if (dmg
> 0 && u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_AK_____
) {
1913 if (P_SKILL(P_FIREARM
) == P_MASTER
) dmg
-= 2;
1914 if (P_SKILL(P_FIREARM
) == P_GRAND_MASTER
) dmg
-= 4;
1915 if (P_SKILL(P_FIREARM
) == P_SUPREME_MASTER
) dmg
-= 6;
1918 if (Race_if(PM_ITAQUE
)) dmg
-= 1;
1919 if (uwep
&& uwep
->oartifact
== ART_RIP_STRATEGY
) dmg
-= 5;
1920 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_RIP_STRATEGY
) dmg
-= 5;
1921 if (uwep
&& uwep
->oartifact
== ART_KLOBB
) dmg
-= 6;
1922 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_KLOBB
) dmg
-= 6;
1923 if (uwep
&& uwep
->oartifact
== ART_EXCALIPOOR
) dmg
-= 9;
1924 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_EXCALIPOOR
) dmg
-= 9;
1925 if (uwep
&& uwep
->oartifact
== ART_VLADSBANE
) dmg
-= 5;
1926 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_VLADSBANE
) dmg
-= 5;
1927 if (uwep
&& uwep
->oartifact
== ART_CHARGING_MADE_EASY
) dmg
-= 5;
1928 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_CHARGING_MADE_EASY
) dmg
-= 5;
1929 if (uwep
&& uwep
->oartifact
== ART_BLACK_MARK
) dmg
-= 1;
1930 if (uarm
&& uarm
->oartifact
== ART_POWASPEL
) dmg
-= 3;
1932 if (dmg
< 0) dmg
= 0; /* beware negative rings of increase damage */
1933 if (Half_physical_damage
&& (rn2(2) || (uwep
&& uwep
->oartifact
== ART_SOOTHE_
)) ) dmg
= (dmg
+ 1) / 2;
1934 if (StrongHalf_physical_damage
&& (rn2(2) || (uwep
&& uwep
->oartifact
== ART_SOOTHE_
)) ) dmg
= (dmg
+ 1) / 2;
1937 if (less_damage
&& dmg
< (Upolyd
? u
.mh
: u
.uhp
)) {
1939 pline("Fortunately, you are wearing a hard helmet.");
1940 } else if (flags
.verbose
&&
1941 !(obj
->otyp
== CORPSE
&& touch_petrifies(&mons
[obj
->corpsenm
])))
1942 Your("%s does not protect you.", xname(uarmh
));
1943 } else if (obj
->otyp
== CORPSE
&& touch_petrifies(&mons
[obj
->corpsenm
])) {
1944 if ((!Stone_resistance
|| (!IntStone_resistance
&& !rn2(20)) ) &&
1945 !(poly_when_stoned(youmonst
.data
) && polymon(PM_STONE_GOLEM
))) {
1947 /* killer_format = KILLED_BY;
1948 killer = "elementary physics";
1949 You("turn to stone.");
1950 if (obj) dropy(obj);
1953 if (Hallucination
&& rn2(10)) pline("Good thing you are already stoned.");
1955 You("start turning to stone.");
1956 Stoned
= Race_if(PM_EROSATOR
) ? 3 : 7;
1957 u
.cnd_stoningcount
++;
1958 delayed_killer
= "elementary physics";
1961 return obj
? TRUE
: FALSE
;
1965 losehp(dmg
, "falling object", KILLED_BY_AN
);
1970 /* return true for weapon meant to be thrown; excludes ammo */
1972 throwing_weapon(obj
)
1975 return (is_missile(obj
) || is_spear(obj
) ||
1976 /* daggers and knife (excludes scalpel) */
1977 (is_blade(obj
) && !is_sword(obj
) &&
1978 (objects
[obj
->otyp
].oc_dir
& PIERCE
)) ||
1979 /* special cases [might want to add AXE] */
1980 obj
->otyp
== WAR_HAMMER
|| obj
->otyp
== AKLYS
|| obj
->otyp
== BLOW_AKLYS
);
1983 /* the currently thrown object is returning to you (not for boomerangs) */
1985 sho_obj_return_to_u(obj
)
1988 /* might already be our location (bounced off a wall) */
1989 if (bhitpos
.x
!= u
.ux
|| bhitpos
.y
!= u
.uy
) {
1990 int x
= bhitpos
.x
- u
.dx
, y
= bhitpos
.y
- u
.dy
;
1992 tmp_at(DISP_FLASH
, obj_to_glyph(obj
));
1993 while(x
!= u
.ux
|| y
!= u
.uy
) {
1996 x
-= u
.dx
; y
-= u
.dy
;
1998 tmp_at(DISP_END
, 0);
2003 throwit(obj
, wep_mask
, twoweap
, thrown
)
2005 long wep_mask
; /* used to re-equip returning boomerang */
2006 boolean twoweap
; /* used to restore twoweapon mode if wielded weapon returns */
2009 register struct monst
*mon
;
2010 register int range
, urange
;
2011 struct obj
*launcher
= (struct obj
*) 0;
2012 boolean impaired
= ( (Confusion
&& !Conf_resist
) || (Stunned
&& !Stun_resist
) || Blind
||
2013 Hallucination
|| Fumbling
|| Frozen
|| Burned
|| Dimmed
|| Numbed
|| Feared
);
2015 if (thrown
== 1) launcher
= uwep
;
2016 else if (thrown
== 2) launcher
= uswapwep
;
2017 else if (thrown
== 666) { /* inbuilt pistol boots */
2018 if (uarmf
&& itemhasappearance(uarmf
, APP_PISTOL_BOOTS
) ) launcher
= uarmf
;
2021 boolean misfire
= FALSE
;
2022 if (obj
->cursed
&& !(uarmg
&& uarmg
->otyp
== GAUNTLETS_OF_TRUE_AIM
) && !(uarmg
&& itemhasappearance(uarmg
, APP_SUREFIRE_GLOVES
)) ) {
2023 if (!rn2(7)) misfire
= TRUE
;
2025 if (obj
->otyp
== FLIMSY_DART
) {
2026 if (!rn2(7)) misfire
= TRUE
;
2028 if (ACURR(A_DEX
) == 1) {
2029 if (!rn2(7)) misfire
= TRUE
;
2031 if (is_grassland(u
.ux
, u
.uy
) && !(uarm
&& uarm
->oartifact
== ART_DORL_TSCH
) && !(uarmf
&& itemhasappearance(uarmf
, APP_GARDEN_SLIPPERS
)) ) {
2032 if (!rn2(7)) misfire
= TRUE
;
2035 if (!rn2(7)) misfire
= TRUE
;
2037 if (Race_if(PM_PLAYER_SKELETON
) && !rn2(3)) {
2038 if (!rn2(7)) misfire
= TRUE
;
2040 if (autismweaponcheck(ART_FOEOEOEOEOEOEOE
)) {
2041 if (!rn2(7)) misfire
= TRUE
;
2043 if (uarmg
&& itemhasappearance(uarmg
, APP_CLUMSY_GLOVES
) ) {
2044 if (!rn2(7)) misfire
= TRUE
;
2046 if ((obj
->oartifact
== ART_COMPLETELY_OFF
) || (obj
->oartifact
== ART_FLUSCH
) || (obj
->oartifact
== ART_STREW_ANYWHERE
) || u
.uprops
[PROJECTILES_MISFIRE
].extrinsic
|| ProjectilesMisfire
|| have_misfirestone() ) misfire
= TRUE
;
2048 /* KMH -- Handle Plague here */
2049 if (launcher
&& (launcher
->oartifact
== ART_PLAGUE
|| launcher
->oartifact
== ART_BOW_OF_VINDERRE
|| launcher
->oartifact
== ART_SHAKING_BOW
|| launcher
->oartifact
== ART_BIBLICAL_PLAGUE
|| launcher
->oartifact
== ART_BOW_OF_HERCULES
) &&
2050 ammo_and_launcher(obj
, launcher
) && is_poisonable(obj
))
2053 if (launcher
&& launcher
->oartifact
== ART_NOZZLE_CHANGE
&& ammo_and_launcher(obj
, launcher
))
2054 obj
->opoisoned
= 1; /* even if it cannot be poisoned, this is not a bug --Amy */
2056 if (uarmf
&& uarmf
->oartifact
== ART_DOUBTLY_POISON
&& is_poisonable(obj
)) {
2057 obj
->opoisoned
= obj
->superpoison
= 1;
2060 if (obj
&& obj
->oartifact
== ART_TROPICAL_WOOD_SELECTION
) obj
->opoisoned
= 1;
2061 if (obj
&& obj
->oartifact
== ART_DART_OF_THE_ASSASSIN
) obj
->opoisoned
= 1;
2063 if (launcher
&& obj
&& ammo_and_launcher(obj
, launcher
) && obj
->otyp
== POISON_BOLT
) obj
->opoisoned
= 1;
2064 if (launcher
&& obj
&& ammo_and_launcher(obj
, launcher
) && obj
->otyp
== CHROME_PELLET
) obj
->opoisoned
= 1;
2066 obj
->was_thrown
= 1;
2067 if (misfire
&& (u
.dx
|| u
.dy
) ) {
2068 boolean slipok
= TRUE
;
2069 if (ammo_and_launcher(obj
, launcher
))
2070 pline("%s!", Tobjnam(obj
, "misfire"));
2072 /* only slip if it's greased or meant to be thrown */
2073 /* Amy edit: well, the item is cursed, so it should malfunction no matter what. See monsters throwing
2074 * cursed potions, which also causes them to slip. */
2075 /*if (obj->greased || throwing_weapon(obj))*/
2076 /* BUG: this message is grammatically incorrect if obj has
2077 a plural name; greased gloves or boots for instance. */
2078 pline("%s as you throw it!", Tobjnam(obj
, "slip"));
2079 /*else slipok = FALSE;*/
2084 if (!u
.dx
&& !u
.dy
) u
.dz
= 1;
2089 if ((u
.dx
|| u
.dy
|| (u
.dz
< 1)) &&
2090 calc_capacity((int)obj
->owt
) > SLT_ENCUMBER
&&
2091 (Upolyd
? (u
.mh
< 5 && u
.mh
!= u
.mhmax
)
2092 : (u
.uhp
< 10 && u
.uhp
!= u
.uhpmax
)) &&
2093 obj
->owt
> (unsigned)((Upolyd
? u
.mh
: u
.uhp
) * 2) &&
2094 !Is_airlevel(&u
.uz
)) {
2095 You("have so little stamina, %s drops from your grasp.",
2097 exercise(A_CON
, FALSE
);
2104 if (launcher
&& launcher
->oartifact
== ART_LEONE_M__GUAGE_SUPER
) {
2105 nomul(-2, "suffering from M3 recoil", TRUE
);
2107 if (launcher
&& launcher
->oartifact
== ART_MOSIN_NAGANT
) {
2108 nomul(-3, "reloading the Mosin-Nagant", TRUE
);
2110 if (obj
&& obj
->otyp
== JUMPING_FLAMER
) {
2111 if (u
.rangedreload
< 3) u
.rangedreload
= 3;
2116 bhitpos
.x
= mon
->mx
;
2117 bhitpos
.y
= mon
->my
;
2119 if (u
.dz
< 0 && (Role_if(PM_VALKYRIE
) || Role_if(PM_VANILLA_VALK
)) &&
2120 (obj
->oartifact
== ART_MJOLLNIR
|| obj
->oartifact
== ART_OTHER_MJOLLNIR
) && !impaired
) {
2121 pline("%s the %s and returns to your hand!",
2122 Tobjnam(obj
, "hit"), ceiling(u
.ux
,u
.uy
));
2124 (void) encumber_msg();
2125 setuwep(obj
, TRUE
, TRUE
);
2126 u
.twoweap
= twoweap
;
2129 if (u
.dz
< 0 && (Role_if(PM_JEDI
) || Role_if(PM_SHADOW_JEDI
) || Role_if(PM_HEDDERJEDI
) || !rn2(2)) &&
2130 is_lightsaber(obj
) && obj
->lamplit
&& !impaired
&&
2131 !(PlayerCannotUseSkills
) && rn2(2) &&
2132 P_SKILL(weapon_type(obj
)) >= P_SKILLED
) {
2133 pline("%s the %s and returns to your hand!",
2134 Tobjnam(obj
, "hit"), ceiling(u
.ux
,u
.uy
));
2136 (void) encumber_msg();
2137 setuwep(obj
, TRUE
, TRUE
);
2138 u
.twoweap
= twoweap
;
2142 * Grenades are armed but are then processed by toss_up/hitfloor
2145 * Bullets just disappear with no message.
2147 * Rockets hit the ceiling/floor and explode.
2149 else if (is_grenade(obj
)) {
2150 arm_bomb(obj
, TRUE
);
2151 You("yell 'Fire in the hole!'");
2152 } else if (obj
->oclass
== VENOM_CLASS
) {
2153 check_shop_obj(obj
, u
.ux
, u
.uy
, TRUE
);
2154 obfree(obj
, (struct obj
*)0);
2156 } else if (is_bullet(obj
) && ammo_and_launcher(obj
, launcher
)) {
2157 if (!Is_airlevel(&u
.uz
) && !Is_waterlevel(&u
.uz
) && !Underwater
2158 && (objects
[obj
->otyp
].oc_dir
& EXPLOSION
)) {
2159 pline("%s hit%s the %s and explodes in a ball of fire!",
2160 Doname2(obj
), (obj
->quan
== 1L) ? "s" : "",
2161 u
.dz
< 0 ? ceiling(u
.ux
, u
.uy
) : surface(u
.ux
, u
.uy
));
2162 explode(u
.ux
, u
.uy
, ZT_SPELL(ZT_FIRE
), d(3, 8),
2163 WEAPON_CLASS
, EXPL_FIERY
);
2165 if (obj
&& obj
->otyp
== MINI_NUKE
) fatman_explosion(u
.ux
, u
.uy
, obj
);
2167 check_shop_obj(obj
, u
.ux
, u
.uy
, TRUE
);
2168 u
.cnd_gunpowderused
++; /* even if bulletreuse or lead bullets allows them to be used again --Amy */
2169 if (((!(tech_inuse(T_BULLETREUSE
)) || rn2(3)) && !(Race_if(PM_VIETIS
) && !rn2(3)) && !(obj
->oartifact
== ART_REUSEME
&& rn2(4)) && !(uarm
&& uarm
->oartifact
== ART_MG_RATTERING
&& (objects
[obj
->otyp
].w_ammotyp
== WP_BULLET_MG
) ) && !(obj
->oartifact
== ART_EVERYTHING_GREENS_SO_GREEN
) && !(obj
->oartifact
== ART_COMBAT_PELLET
&& rn2(10)) && !(objects
[obj
->otyp
].oc_material
== MT_LEAD
&& !rn2(2))) || (uarmf
&& uarmf
->oartifact
== ART_ANACONDA_HEELS
) ) {
2170 obfree(obj
, (struct obj
*)0);
2174 if (u
.dz
< 0 && !Is_airlevel(&u
.uz
) &&
2175 !Underwater
&& !is_crystalwater(u
.ux
, u
.uy
) && !Is_waterlevel(&u
.uz
)) {
2176 (void) toss_up(obj
, rn2(5));
2180 thrownobj
= (struct obj
*)0;
2183 } else if( (obj
->otyp
== BOOMERANG
|| obj
->otyp
== ALU_BOOMERANG
|| obj
->otyp
== SILVER_CHAKRAM
|| obj
->otyp
== BATARANG
|| obj
->otyp
== DARK_BATARANG
) && !Underwater
) {
2184 if(Is_airlevel(&u
.uz
) || Levitation
)
2185 hurtle(-u
.dx
, -u
.dy
, 1, TRUE
);
2186 mon
= boomhit(u
.dx
, u
.dy
);
2187 if(mon
== &youmonst
) { /* the thing was caught */
2188 exercise(A_DEX
, TRUE
);
2190 (void) encumber_msg();
2191 if (wep_mask
&& !(obj
->owornmask
& wep_mask
)) {
2192 setworn(obj
, wep_mask
);
2193 u
.twoweap
= twoweap
;
2195 thrownobj
= (struct obj
*)0;
2199 /* note to self by Amy: urange is not the range of the thrown thing - range is!!! */
2200 urange
= (int)(ACURRSTR
)/2;
2202 /* balls are easy to throw or at least roll */
2203 /* also, this insures the maximum range of a ball is greater
2204 * than 1, so the effects from throwing attached balls are
2207 if (obj
->oclass
== BALL_CLASS
)
2208 range
= urange
- (int)(obj
->owt
/600); /* thanks to the ball's weight being 2400 now */
2210 range
= urange
- (int)(obj
->owt
/40);
2212 if (u
.ustuck
) range
= 1;
2213 else if (range
>= 5) range
= 5;
2215 if (range
< 1) range
= 1;
2217 /* KMH, balance patch -- new macros */
2219 if ( (ammo_and_launcher(obj
, launcher
) && !(launcher
&& launcher
->otyp
== LASERXBOW
&& !launcher
->lamplit
) && !(launcher
&& launcher
->otyp
== KLIUSLING
&& !launcher
->lamplit
) ) ) {
2220 if (is_launcher(launcher
) &&
2221 objects
[(launcher
->otyp
)].oc_range
)
2222 range
= objects
[(launcher
->otyp
)].oc_range
;
2225 } else if (obj
->oclass
!= GEM_CLASS
)
2228 if (thrown
== 666) range
= 15;
2230 if (uarmh
&& uarmh
->oartifact
== ART_VIRUS_ATTACK
) range
+= 2;
2231 if (launcher
&& ammo_and_launcher(obj
, launcher
) && launcher
->otyp
== SNIPESLING
&& obj
) range
+= 5;
2232 if (launcher
&& ammo_and_launcher(obj
, launcher
) && launcher
->otyp
== BLUE_BOW
&& obj
) range
+= 1;
2233 if (launcher
&& ammo_and_launcher(obj
, launcher
) && launcher
->oartifact
== ART_TSCHUEUU
&& obj
) range
+= 10;
2234 if (launcher
&& (ammo_and_launcher(obj
, launcher
) && !(launcher
&& launcher
->otyp
== LASERXBOW
&& !launcher
->lamplit
) ) && obj
&& obj
->otyp
== ETHER_BOLT
) range
+= 2;
2235 if (obj
&& obj
->oartifact
== ART_LONG_RANGE_BALLISTICS
) range
+= 5;
2236 if (launcher
&& ammo_and_launcher(obj
, launcher
) && obj
->oartifact
== ART_SNIPESNIPESNIPE
) range
+= 5;
2237 if (obj
&& obj
->oartifact
== ART_WAY_TOO_LONG
) range
+= 10;
2238 if (launcher
&& ammo_and_launcher(obj
, launcher
) && obj
->oartifact
== ART_SAY__CHESS_
) range
+= 2;
2239 if (obj
&& obj
->oartifact
== ART_PEWWWWWWW
) range
+= 15;
2240 if (obj
&& obj
->oartifact
== ART_WIUNEW
) range
+= 3;
2241 if (obj
&& obj
->oartifact
== ART_KLUEUEUEU
) range
+= 5;
2242 if (obj
&& obj
->oartifact
== ART_GEHENNA_MODE
&& ( (Inhell
&& !Race_if(PM_HERETIC
) ) || flags
.gehenna
) ) range
+= 4;
2243 if (uwep
&& uwep
->oartifact
== ART_GEHENNA_MODE
&& ( (Inhell
&& !Race_if(PM_HERETIC
) ) || flags
.gehenna
) ) range
+= 3;
2245 if (!PlayerCannotUseSkills
&& launcher
&& ammo_and_launcher(obj
, launcher
) && launcher
->otyp
== KLIUSLING
&& launcher
->lamplit
) {
2246 if (u
.kliuskill
>= 20) range
++;
2247 if (u
.kliuskill
>= 160) range
++;
2248 if (u
.kliuskill
>= 540) range
++;
2249 if (u
.kliuskill
>= 1280) range
++;
2250 if (u
.kliuskill
>= 2500) range
++;
2251 if (u
.kliuskill
>= 4320) range
++;
2254 if (!PlayerCannotUseSkills
&& obj
&& obj
->oartifact
== ART_WEDIFORCE
) {
2255 switch (P_SKILL(P_WEDI
)) {
2256 case P_BASIC
: range
+= 1; break;
2257 case P_SKILLED
: range
+= 2; break;
2258 case P_EXPERT
: range
+= 3; break;
2259 case P_MASTER
: range
+= 4; break;
2260 case P_GRAND_MASTER
: range
+= 5; break;
2261 case P_SUPREME_MASTER
: range
+= 6; break;
2266 if (Race_if(PM_ENGCHIP
) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) range
+= 2;
2267 if (Race_if(PM_ENGCHIP
) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_CROSSBOW
) range
+= 2;
2268 if (Race_if(PM_KORONST
) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_SLING
) range
+= 2;
2270 if (uarmg
&& uarmg
->oartifact
== ART_BEEEEEEEANPOLE
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) range
+= 5;
2271 if (uwep
&& uwep
->oartifact
== ART_SNIPER_CROSSHAIR
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_CROSSBOW
) range
+= 30;
2272 if ((uarmc
&& itemhasappearance(uarmc
, APP_CYANISM_CLOAK
)) && launcher
&& objects
[launcher
->otyp
].oc_skill
== P_SLING
) range
+= 3;
2273 if (launcher
&& launcher
->oartifact
== ART_ITALY_SI_ES
) range
+= 4;
2274 if (launcher
&& launcher
->oartifact
== ART_MISS_LAUNCHER
) range
+= 2;
2275 if (launcher
&& launcher
->oartifact
== ART_ACTUALLY_USABLE_GL
) range
+= 6;
2276 if (obj
&& obj
->oartifact
== ART_MEGATON_LOAD
) range
+= 10;
2277 if (obj
&& obj
->oartifact
== ART_A_MILE_AND_A_HALF
) range
+= 25;
2278 if (obj
&& obj
->oartifact
== ART_LONG_MILE
) range
+= 5;
2279 if (obj
&& obj
->oartifact
== ART_FLAI_AWEI
) range
+= 10;
2280 if (obj
&& obj
->oartifact
== ART_NINJINGY
) range
+= 2;
2281 if (obj
&& obj
->oartifact
== ART_FTS
) range
+= 10;
2282 if (obj
&& obj
->oartifact
== ART_WASHINGTON_S_CAPPER
) range
+= 5;
2283 if (uarmu
&& uarmu
->oartifact
== ART_NOW_YOU_MADE_HER_SAD
) range
+= 2;
2285 if (obj
&& obj
->oartifact
== ART_RACER_PROJECTILE
) range
*= 2;
2287 if (launcher
&& launcher
->oartifact
== ART_ENEMY_DEAD_AT_CLOSE_RANGE
) range
--;
2289 if (Race_if(PM_GERTEUT
) && range
> 5) range
= 5;
2290 if (Race_if(PM_PERVERT
) && range
> 2) range
= 2;
2291 if (launcher
&& launcher
->otyp
== SHOVEL
&& range
> 4) range
= 4;
2292 if (launcher
&& launcher
->oartifact
== ART_OZYZEVPDWTVP
) range
-= 2;
2294 if (range
< 1) range
= 1; /* fail safe */
2296 if (Is_airlevel(&u
.uz
) || Levitation
) {
2297 /* action, reaction... */
2299 if(urange
< 1) urange
= 1;
2301 if(range
< 1) range
= 1;
2304 if (obj
->otyp
== BOULDER
)
2305 range
= 20; /* you must be giant */
2306 else if (obj
->oartifact
== ART_MJOLLNIR
|| obj
->oartifact
== ART_OTHER_MJOLLNIR
)
2307 range
= (range
+ 1) / 2; /* it's heavy */
2308 else if (obj
== uball
&& u
.utrap
&& u
.utraptype
== TT_INFLOOR
)
2311 if (Underwater
) range
= 1;
2313 if (Race_if(PM_GERTEUT
) && range
> 5) range
= 5;
2314 if (Race_if(PM_PERVERT
) && range
> 2) range
= 2;
2316 if (range
< 1) range
= 1; /* fail safe */
2318 mon
= bhit(u
.dx
,u
.dy
,range
,THROWN_WEAPON
,
2319 (int (*)(MONST_P
,OBJ_P
))0,
2320 (int (*)(OBJ_P
,OBJ_P
))0,
2323 /* have to do this after bhit() so u.ux & u.uy are correct */
2324 if(Is_airlevel(&u
.uz
) || Levitation
)
2325 hurtle(-u
.dx
, -u
.dy
, urange
, TRUE
);
2328 thrownobj
= (struct obj
*)0;
2337 obj
->where
== OBJ_MINVENT
&& obj
->ocarry
== mon
) {
2338 thrownobj
= (struct obj
*)0;
2339 return; /* alert shk caught it */
2341 (void) snuff_candle(obj
);
2342 notonhead
= (bhitpos
.x
!= mon
->mx
|| bhitpos
.y
!= mon
->my
);
2343 obj_gone
= thitmonst(mon
, obj
, thrown
, FALSE
);
2344 /* Monster may have been tamed; this frees old mon */
2345 mon
= m_at(bhitpos
.x
, bhitpos
.y
);
2347 /* [perhaps this should be moved into thitmonst or hmon] */
2348 if (mon
&& mon
->isshk
&&
2349 (!inside_shop(u
.ux
, u
.uy
) ||
2350 !index(in_rooms(mon
->mx
, mon
->my
, SHOPBASE
), *u
.ushops
)))
2353 if (obj_gone
) return;
2356 /* Handle grenades or rockets */
2357 if (is_grenade(obj
)) {
2358 arm_bomb(obj
, TRUE
);
2359 You("yell 'Fire in the hole!'");
2360 } else if (ammo_and_launcher(obj
, launcher
) &&
2361 (objects
[obj
->otyp
].oc_dir
& EXPLOSION
)) {
2362 if (cansee(bhitpos
.x
,bhitpos
.y
))
2363 pline("%s explodes in a ball of fire!", Doname2(obj
));
2364 else You_hear("an explosion");
2365 explode(bhitpos
.x
, bhitpos
.y
, ZT_SPELL(ZT_FIRE
),
2366 d(3,8), WEAPON_CLASS
, EXPL_FIERY
);
2368 if (obj
&& obj
->otyp
== MINI_NUKE
) fatman_explosion(bhitpos
.x
, bhitpos
.y
, obj
);
2371 if (obj
->oclass
== VENOM_CLASS
) {
2372 check_shop_obj(obj
, bhitpos
.x
,bhitpos
.y
, TRUE
);
2373 obfree(obj
, (struct obj
*)0);
2377 if (is_bullet(obj
) && (ammo_and_launcher(obj
, launcher
) && !is_grenade(obj
))) {
2378 check_shop_obj(obj
, bhitpos
.x
,bhitpos
.y
, TRUE
);
2379 u
.cnd_gunpowderused
++; /* even if bulletreuse or lead bullets allows them to be used again --Amy */
2380 if (((!(tech_inuse(T_BULLETREUSE
)) || rn2(3)) && !(Race_if(PM_VIETIS
) && !rn2(3)) && !(obj
->oartifact
== ART_REUSEME
&& rn2(4)) && !(uarm
&& uarm
->oartifact
== ART_MG_RATTERING
&& (objects
[obj
->otyp
].w_ammotyp
== WP_BULLET_MG
) ) && !(obj
->oartifact
== ART_EVERYTHING_GREENS_SO_GREEN
) && !(obj
->oartifact
== ART_COMBAT_PELLET
&& rn2(10)) && !(objects
[obj
->otyp
].oc_material
== MT_LEAD
&& !rn2(2))) || (uarmf
&& uarmf
->oartifact
== ART_ANACONDA_HEELS
) ) {
2381 obfree(obj
, (struct obj
*)0);
2386 int djemsochance
= 0;
2388 if (!PlayerCannotUseSkills
) {
2389 switch (P_SKILL(P_DJEM_SO
)) {
2391 case P_BASIC
: djemsochance
= 1; break;
2392 case P_SKILLED
: djemsochance
= 2; break;
2393 case P_EXPERT
: djemsochance
= 4; break;
2394 case P_MASTER
: djemsochance
= 6; break;
2395 case P_GRAND_MASTER
: djemsochance
= 8; break;
2396 case P_SUPREME_MASTER
: djemsochance
= 9; break;
2397 default: djemsochance
= 0; break;
2401 /* boomerang can come back, idea from dnethack, implementation by Amy (chance is less than 100%) */
2402 int boomerangchance
= 20;
2404 if (!PlayerCannotUseSkills
) {
2405 switch (P_SKILL(P_BOOMERANG
)) {
2407 case P_BASIC
: boomerangchance
= 30; break;
2408 case P_SKILLED
: boomerangchance
= 35; break;
2409 case P_EXPERT
: boomerangchance
= 40; break;
2410 case P_MASTER
: boomerangchance
= 50; break;
2411 case P_GRAND_MASTER
: boomerangchance
= 60; break;
2412 case P_SUPREME_MASTER
: boomerangchance
= 70; break;
2413 default: boomerangchance
= 20; break;
2416 switch (P_SKILL(P_DJEM_SO
)) {
2418 case P_BASIC
: boomerangchance
+= 2; break;
2419 case P_SKILLED
: boomerangchance
+= 4; break;
2420 case P_EXPERT
: boomerangchance
+= 6; break;
2421 case P_MASTER
: boomerangchance
+= 8; break;
2422 case P_GRAND_MASTER
: boomerangchance
+= 10; break;
2423 case P_SUPREME_MASTER
: boomerangchance
+= 12; break;
2427 if (boomerangchance
> 90) boomerangchance
= 90; /* shouldn't happen */
2429 if (Race_if(PM_BATMAN
)) { /* his batarang usually comes back --Amy */
2430 boomerangchance
+= ((100 - boomerangchance
) / 2);
2435 /* ball is not picked up by monster */
2436 if (obj
!= uball
) (void) mpickobj(u
.ustuck
,obj
,FALSE
);
2438 /* the code following might become part of dropy() */
2440 (obj
->oartifact
== ART_MJOLLNIR
&& Role_if(PM_VALKYRIE
) && rn2(100)) ||
2441 (obj
->oartifact
== ART_OTHER_MJOLLNIR
&& Role_if(PM_VALKYRIE
) && rn2(100)) ||
2442 (obj
->oartifact
== ART_MJOLLNIR
&& Role_if(PM_VANILLA_VALK
) && rn2(100)) ||
2443 (obj
->oartifact
== ART_OTHER_MJOLLNIR
&& Role_if(PM_VANILLA_VALK
) && rn2(100)) ||
2445 (is_lightsaber(obj
) && (obj
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) && (rn2(2) || (djemsochance
>= rn2(11)) ) &&
2446 ( ( (Role_if(PM_JEDI
) || Role_if(PM_SHADOW_JEDI
) || Role_if(PM_HEDDERJEDI
)) && P_SKILL(weapon_type(obj
)) > P_SKILLED
) || (!rn2(2) && P_SKILL(weapon_type(obj
)) > P_SKILLED
) || (djemsochance
>= rn2(11)) ) ) ||
2448 ((objects
[obj
->otyp
].oc_skill
== P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== -P_BOOMERANG
) &&
2449 ((boomerangchance
> rn2(100)) || (obj
->oartifact
&& !rn2(3)) ) )
2453 boolean boomerfix
= (objects
[obj
->otyp
].oc_skill
== P_BOOMERANG
|| objects
[obj
->otyp
].oc_skill
== -P_BOOMERANG
);
2455 /* we must be wearing Gauntlets of Power to get here */
2456 /* or a Jedi with a lightsaber or a thrown boomerang */
2457 if ( (Role_if(PM_JEDI
) || Role_if(PM_SHADOW_JEDI
) || Role_if(PM_HEDDERJEDI
)) && u
.uen
< 5){
2458 You("don't have enough force to call %s. You need at least 5 points of mana!", the(xname(obj
)));
2460 if (Role_if(PM_JEDI
) || Role_if(PM_SHADOW_JEDI
) || Role_if(PM_HEDDERJEDI
))
2462 if (!boomerfix
) sho_obj_return_to_u(obj
); /* display its flight */
2464 /* djem so just trains so damn slowly... so here's an improvement --Amy */
2465 if (is_lightsaber(obj
)) {
2466 use_skill(P_DJEM_SO
, 1);
2467 if (obj
->otyp
== PINK_LIGHTSWORD
|| obj
->otyp
== PINK_DOUBLE_LIGHTSWORD
) use_skill(P_DJEM_SO
, 1);
2468 if (obj
->oartifact
== ART_ROSH_TRAINOR
) use_skill(P_DJEM_SO
, 1);
2471 if (!impaired
&& rn2(100)) {
2472 pline("%s to your hand!", Tobjnam(obj
, "return"));
2473 if (is_lightsaber(obj
)) mightbooststat(A_DEX
);
2475 (void) encumber_msg();
2477 setuwep(obj
, TRUE
, TRUE
);
2478 u
.twoweap
= twoweap
;
2482 if(cansee(bhitpos
.x
, bhitpos
.y
))
2483 newsym(bhitpos
.x
,bhitpos
.y
);
2487 pline(Blind
? "%s lands %s your %s." :
2488 "%s back to you, landing %s your %s.",
2489 Blind
? Something
: Tobjnam(obj
, "return"),
2490 Levitation
? "beneath" : "at",
2491 makeplural(body_part(FOOT
)));
2494 pline(Blind
? "%s your %s!" :
2495 "%s back toward you, hitting your %s!",
2496 Tobjnam(obj
, Blind
? "hit" : "fly"),
2498 (void) artifact_hit((struct monst
*)0,
2499 &youmonst
, obj
, &dmg
, 0);
2500 losehp(dmg
, xname(obj
),
2501 obj_is_pname(obj
) ? KILLED_BY
: KILLED_BY_AN
);
2503 if (ship_object(obj
, u
.ux
, u
.uy
, FALSE
)) {
2504 thrownobj
= (struct obj
*)0;
2509 thrownobj
= (struct obj
*)0;
2514 if (!IS_SOFT(levl
[bhitpos
.x
][bhitpos
.y
].typ
) &&
2516 tmp_at(DISP_FLASH
, obj_to_glyph(obj
));
2517 tmp_at(bhitpos
.x
, bhitpos
.y
);
2519 tmp_at(DISP_END
, 0);
2520 breakmsg(obj
, cansee(bhitpos
.x
, bhitpos
.y
));
2521 if (issegfaulter
&& obj
->otyp
== SEGFAULT_VENOM
&& !rn2(5)) { /* segfault panic! */
2522 u
.segfaultpanic
= TRUE
;
2523 } else if (obj
->oartifact
== ART_DO_NOT_THROW_ME
) { /* uh-oh... you really messed up big time there. */
2524 u
.segfaultpanic
= TRUE
;
2526 breakobj(obj
, bhitpos
.x
, bhitpos
.y
, TRUE
, TRUE
);
2529 if(flooreffects(obj
,bhitpos
.x
,bhitpos
.y
,"fall")) return;
2530 obj_no_longer_held(obj
);
2531 if (mon
&& mon
->isshk
&& is_pick(obj
)) {
2532 if (cansee(bhitpos
.x
, bhitpos
.y
))
2533 pline("%s snatches up %s.",
2534 Monnam(mon
), the(xname(obj
)));
2536 check_shop_obj(obj
, bhitpos
.x
, bhitpos
.y
, FALSE
);
2537 (void) mpickobj(mon
, obj
, FALSE
); /* may merge and free obj */
2538 thrownobj
= (struct obj
*)0;
2541 (void) snuff_candle(obj
);
2542 if (!mon
&& ship_object(obj
, bhitpos
.x
, bhitpos
.y
, FALSE
)) {
2543 thrownobj
= (struct obj
*)0;
2546 thrownobj
= (struct obj
*)0;
2547 place_object(obj
, bhitpos
.x
, bhitpos
.y
);
2548 if(*u
.ushops
&& obj
!= uball
)
2549 check_shop_obj(obj
, bhitpos
.x
, bhitpos
.y
, FALSE
);
2553 drop_ball(bhitpos
.x
, bhitpos
.y
);
2554 if (cansee(bhitpos
.x
, bhitpos
.y
))
2555 newsym(bhitpos
.x
,bhitpos
.y
);
2556 if (obj_sheds_light(obj
))
2557 vision_full_recalc
= 1;
2558 if (!IS_SOFT(levl
[bhitpos
.x
][bhitpos
.y
].typ
))
2559 container_impact_dmg(obj
);
2563 /* an object may hit a monster; various factors adjust the chance of hitting */
2565 omon_adj(mon
, obj
, mon_notices
)
2568 boolean mon_notices
;
2572 /* size of target affects the chance of hitting */
2573 tmp
+= (mon
->data
->msize
- MZ_MEDIUM
); /* -2..+5 */
2574 /* sleeping target is more likely to be hit */
2575 if (mon
->msleeping
) {
2577 if (mon_notices
) mon
->msleeping
= 0;
2579 /* ditto for immobilized target */
2580 if (!mon
->mcanmove
|| !mon
->data
->mmove
) {
2582 if (mon_notices
&& mon
->data
->mmove
&& !rn2(mon
->masleep
? 3 : 10)) {
2588 /* some objects are more likely to hit than others */
2589 switch (obj
->otyp
) {
2590 case HEAVY_IRON_BALL
:
2591 if (obj
!= uball
) tmp
+= 2;
2595 if (!PlayerCannotUseSkills
) {
2596 switch (P_SKILL(P_BOULDER_THROWING
)) {
2598 case P_BASIC
: tmp
+= 2; break;
2599 case P_SKILLED
: tmp
+= 4; break;
2600 case P_EXPERT
: tmp
+= 6; break;
2601 case P_MASTER
: tmp
+= 8; break;
2602 case P_GRAND_MASTER
: tmp
+= 10; break;
2603 case P_SUPREME_MASTER
: tmp
+= 12; break;
2609 if (obj
->oclass
== WEAPON_CLASS
|| obj
->oclass
== BALL_CLASS
|| obj
->oclass
== CHAIN_CLASS
|| obj
->oclass
== VENOM_CLASS
|| is_weptool(obj
) || obj
->oclass
== GEM_CLASS
)
2610 tmp
+= hitval(obj
, mon
);
2616 /* thrown object misses target monster */
2622 const char *missile
= mshot_xname(obj
);
2624 /* If the target can't be seen or doesn't look like a valid target,
2625 avoid "the arrow misses it," or worse, "the arrows misses the mimic."
2626 An attentive player will still notice that this is different from
2627 an arrow just landing short of any target (no message in that case),
2628 so will realize that there is a valid target here anyway. */
2629 if (!canseemon(mon
) || (mon
->m_ap_type
&& mon
->m_ap_type
!= M_AP_MONSTER
))
2630 pline("%s %s.", The(missile
), otense(obj
, "miss"));
2633 if (!rn2(3)) wakeup(mon
);
2635 if ( (autismweaponcheck(ART_CANNONDANCER
)) && multi
>= 0) {
2636 if (isstunfish
) nomul(-(rnz(10)), "having missed the beat", TRUE
);
2637 else nomul(-(rn1(5,5)), "having missed the beat", TRUE
);
2644 #define quest_arti_hits_leader(obj,mon) \
2645 (obj->oartifact && is_quest_artifact(obj) && (mon->data->msound == MS_LEADER))
2648 * Object thrown by player arrives at monster's location.
2649 * Return 1 if obj has disappeared or otherwise been taken care of,
2650 * 0 if caller must take care of it.
2653 thitmonst(mon
, obj
, thrown
, polearming
)
2654 register struct monst
*mon
;
2655 register struct obj
*obj
;
2659 register int tmp
; /* Base chance to hit */
2660 register int disttmp
; /* distance modifier */
2661 struct obj
*launcher
;
2662 register struct obj
*blocker
= (struct obj
*)0;
2663 boolean doubleshot
= FALSE
; /* are you dual-wielding and firing with the secondary weapon as well? */
2665 int skillpierce
; /* with high skill, you can hit monsters that would normally have dodged --Amy */
2667 int otyp
= obj
->otyp
;
2668 boolean guaranteed_hit
= (u
.uswallow
&& mon
== u
.ustuck
&& rn2(3));
2669 int dieroll
= rnd(20);
2671 boolean stupidrock
= 0;
2672 if (obj
->otyp
== ROCK
) stupidrock
= 1;
2674 boolean bulletate
= 0;
2675 if (objects
[obj
->otyp
].oc_skill
== P_FIREARM
|| objects
[obj
->otyp
].oc_skill
== -P_FIREARM
) bulletate
= 1;
2678 if (objects
[obj
->otyp
].oc_skill
== P_POLEARMS
) pieks
= 1;
2679 if (objects
[obj
->otyp
].oc_skill
== P_LANCE
) pieks
= 1;
2680 if (obj
->otyp
== GRAPPLING_HOOK
) pieks
= 1;
2681 if (obj
->otyp
== LAJATANG
) pieks
= 1;
2682 if (obj
->otyp
== JACK_KNIFE
) pieks
= 1;
2683 boolean stopevading
= 0;
2684 if (obj
->oartifact
== ART_STOP_EVADING_ME
) stopevading
= 1;
2686 register int shieldblockrate
= 0;
2688 /* Differences from melee weapons:
2690 * Dex still gives a bonus, but strength does not.
2691 * Polymorphed players lacking attacks may still throw.
2692 * There's a base -1 to hit.
2693 * No bonuses for fleeing or stunned targets (they don't dodge
2694 * melee blows as readily, but dodging arrows is hard anyway).
2695 * Not affected by traps, etc.
2696 * Certain items which don't in themselves do damage ignore tmp.
2697 * Distance and monster size affect chance to hit.
2699 /* KMH -- added ring of increase accuracy */
2701 if (thrown
== 1) launcher
= uwep
;
2702 else if (thrown
== 2) launcher
= uswapwep
;
2703 else if (thrown
== 666) { /* inbuilt pistol boots */
2704 if (uarmf
&& itemhasappearance(uarmf
, APP_PISTOL_BOOTS
) ) launcher
= uarmf
;
2706 else launcher
= (struct obj
*)0;
2708 if (u
.twoweap
&& uswapwep
&& launcher
&& (uswapwep
== launcher
)) doubleshot
= TRUE
;
2710 boolean gunused
= 0;
2711 if (launcher
&& ammo_and_launcher(obj
, launcher
) && objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) gunused
= 1;
2713 tmp
= -1 + ( (!rn2(3) && Luck
> 0) ? rnd(Luck
) : Luck
) + find_mac(mon
) + ((increase_accuracy_bonus_value() > 1) ? rnd(increase_accuracy_bonus_value()) : increase_accuracy_bonus_value()) +
2714 (!rn2(3) ? (maybe_polyd(rnd(youmonst
.data
->mlevel
+ 1), rnd(GushLevel
))) : (maybe_polyd(youmonst
.data
->mlevel
+ 1, GushLevel
)) );
2716 /* early-game bonuses to make starting characters not suck too badly --Amy */
2717 if (u
.ulevel
< 6) tmp
+= 1;
2718 if (u
.ulevel
< 4) tmp
+= 1; /* because abon() somehow doesn't get factored in */
2719 if (u
.ulevel
< 2) tmp
+= 1;
2720 if (u
.ulevel
< 5 && rn2(2)) tmp
+= 1;
2721 if (u
.ulevel
< 3 && rn2(2)) tmp
+= 1;
2723 if (GushLevel
> 5) tmp
+= 1;
2724 if (GushLevel
> 9) tmp
+= 1;
2725 if (GushLevel
> 12) tmp
+= 1;
2726 if (GushLevel
> 15) tmp
+= 1;
2727 if (GushLevel
> 19) tmp
+= 1;
2728 if (GushLevel
> 23) tmp
+= 1;
2729 if (GushLevel
> 26) tmp
+= 1;
2730 if (GushLevel
> 29) tmp
+= 1;
2732 if (!issoviet
&& !rn2(3)) tmp
+= rno(GushLevel
);
2734 if (uarmh
&& uarmh
->oartifact
== ART_REMOTE_GAMBLE
) tmp
+= 2;
2735 if (uarm
&& uarm
->oartifact
== ART_MOTHERFUCKER_TROPHY
) tmp
+= 5;
2736 if (u
.tiksrvzllatdown
) tmp
+= 5;
2738 if (Race_if(PM_GERTEUT
)) tmp
+= 5;
2740 if (obj
&& obj
->otyp
== LASER_FLYAXE
&& obj
->lamplit
) tmp
+= 5;
2741 if (obj
&& obj
->otyp
== DISKOS
) tmp
+= 5;
2742 if (obj
&& obj
->otyp
== TOMAHAWK
) tmp
+= 5;
2743 if (obj
&& obj
->oartifact
== ART_LONG_RANGE_BALLISTICS
) tmp
+= 10;
2745 if (uarmh
&& uarmh
->oartifact
== ART_B_A_L_L_A_S
&& gunused
) tmp
+= 3;
2747 if (uarmf
&& uarmf
->oartifact
== ART_WE_ARE__TRANNIES
&& gunused
) tmp
+= rnd(10);
2749 if (uarmg
&& itemhasappearance(uarmg
, APP_UNCANNY_GLOVES
)) tmp
+= 1;
2750 if (uarmg
&& itemhasappearance(uarmg
, APP_SLAYING_GLOVES
)) tmp
+= 1;
2751 if (uarmg
&& itemhasappearance(uarmg
, APP_SUREFIRE_GLOVES
)) tmp
+= 2;
2752 if (uarmg
&& uarmg
->otyp
== GAUNTLETS_OF_TRUE_AIM
) {
2754 if (uarmg
->spe
> 0) tmp
+= uarmg
->spe
;
2757 if (uarmh
&& uarmh
->oartifact
== ART_IRON_HELM_OF_GORLIM
) tmp
+= 10;
2758 if (uarmh
&& uarmh
->oartifact
== ART_SUDUNSEL
) tmp
+= 2;
2759 if (uarm
&& uarm
->otyp
== DARK_DRAGON_SCALES
) tmp
+= 1;
2760 if (uarm
&& uarm
->otyp
== DARK_DRAGON_SCALE_MAIL
) tmp
+= 1;
2761 if (uarms
&& uarms
->otyp
== DARK_DRAGON_SCALE_SHIELD
) tmp
+= 1;
2762 if (uarmg
&& uarmg
->oartifact
== ART_FLOEMMELFLOEMMELFLOEMMELFL
) tmp
+= 1;
2763 if (uarmf
&& uarmf
->oartifact
== ART_MELISSA_S_BEAUTY
) tmp
+= 5;
2764 if (uarmf
&& uarmf
->oartifact
== ART_MAY_BRITT_S_ADULTHOOD
) tmp
-= 2;
2765 if (uwep
&& uwep
->oartifact
== ART_WILD_HEAVY_SWINGS
) tmp
-= 10;
2766 if (uwep
&& uwep
->oartifact
== ART_RAFSCHAR_S_SUPERWEAPON
) tmp
+= 1;
2767 if (uarmc
&& uarmc
->oartifact
== ART_ENEMIES_SHALL_LAUGH_TOO
) tmp
+= 10;
2768 if (uimplant
&& uimplant
->oartifact
== ART_ACTUAL_PRECISION
) tmp
+= 5;
2769 if (uimplant
&& uimplant
->oartifact
== ART_RHEA_S_MISSING_EYESIGHT
) tmp
-= rnd(20);
2770 if (uwep
&& uwep
->oartifact
== ART_SIGIX_BROADSWORD
) tmp
-= 5;
2771 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_SIGIX_BROADSWORD
) tmp
-= 5;
2772 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_ACTUAL_PRECISION
) tmp
+= 5;
2773 if (uleft
&& uleft
->oartifact
== ART_BLIND_PILOT
) tmp
-= 10;
2774 if (uright
&& uright
->oartifact
== ART_BLIND_PILOT
) tmp
-= 10;
2775 if (Role_if(PM_ARCHEOLOGIST
) && uamul
&& uamul
->oartifact
== ART_ARCHEOLOGIST_SONG
) tmp
+= 2;
2776 if (u
.boosttimer
) tmp
+= 5;
2777 if (ublindf
&& ublindf
->oartifact
== ART_EYEHANDER
) tmp
+= 5;
2778 if (uarmg
&& uarmg
->oartifact
== ART_SOFT_TO_THE_TOUCH
) tmp
+= 5;
2779 if (uwep
&& uwep
->oartifact
== ART_JUSTICE_FOR_GARLIC
) tmp
+= 5;
2780 if (uwep
&& uwep
->oartifact
== ART_ATOMIC_MISSING
) tmp
-= 20;
2781 if (uarmg
&& uarmg
->oartifact
== ART_SI_OH_WEE
) tmp
+= 2;
2782 if (uimplant
&& uimplant
->oartifact
== ART_SOME_LITTLE_AID
) tmp
+= 1;
2783 if (uwep
&& uwep
->oartifact
== ART_RIP_STRATEGY
) tmp
-= 5;
2784 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_RIP_STRATEGY
) tmp
-= 5;
2785 if (uarmf
&& uarmf
->oartifact
== ART_CRASHING_YOUR_SISTER_S_WED
) tmp
-= 5;
2786 if (uarmf
&& uarmf
->oartifact
== ART_CAT_ROCKZ
) tmp
+= 5;
2787 if (Race_if(PM_SERB
)) tmp
+= 1;
2788 if (uarmg
&& uarmg
->oartifact
== ART_MAJOR_PRESENCE
) tmp
+= 2;
2789 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 0) tmp
+= 1;
2790 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 49) tmp
+= 1;
2791 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 99) tmp
+= 1;
2792 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 149) tmp
+= 1;
2793 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 199) tmp
+= 1;
2794 if (uwep
&& uwep
->oartifact
== ART_SINSWORD
&& u
.ualign
.record
< 249) tmp
+= 1;
2795 if (StrongBlind_resistance
) tmp
+= rn1(5, 5);
2796 if (uarmh
&& uarmh
->oartifact
== ART_WAITING_FOR_MELEE
) tmp
-= 2;
2797 if (bmwride(ART_KERSTIN_S_COWBOY_BOOST
)) tmp
+= 2;
2798 if (uwep
&& uwep
->oartifact
== ART_VLADSBANE
) tmp
-= 5;
2799 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_VLADSBANE
) tmp
-= 5;
2800 if (uwep
&& uwep
->oartifact
== ART_CHARGING_MADE_EASY
) tmp
-= 5;
2801 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_CHARGING_MADE_EASY
) tmp
-= 5;
2802 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_DUAL_MASTERY
) tmp
+= 5;
2803 if (uwep
&& uwep
->oartifact
== ART_SPINESHOOTER
) tmp
+= 5;
2804 if (uarmf
&& uarmf
->oartifact
== ART_PROPERTY_GRUMBLE
) tmp
-= 5;
2805 if (uarmg
&& uarmg
->oartifact
== ART_UNKNOWINGNESS_AS_A_WEAPON
&& !(objects
[uarmg
->otyp
].oc_name_known
)) tmp
+= 5;
2806 if (uwep
&& uwep
->oartifact
== ART_FALCO_S_ORB
) tmp
+= 1;
2807 if (uwep
&& uwep
->oartifact
== ART_VERY_SPECIFICNESS
) tmp
+= 1;
2808 if (uarmg
&& uarmg
->oartifact
== ART_PLUS_TO_HIT
) tmp
+= 5;
2809 if (uarmh
&& uarmh
->oartifact
== ART_BE_THE_LITE
) tmp
+= 1;
2810 if (uarms
&& uarms
->oartifact
== ART_RONDITSCH
) tmp
+= 1;
2811 if (powerfulimplants() && uimplant
&& uimplant
->oartifact
== ART_NIOBE_S_ANGER
) tmp
+= 4;
2812 if (obj
&& objects
[obj
->otyp
].oc_material
== MT_ADAMANTIUM
) tmp
+= 2;
2813 if (uimplant
&& uimplant
->oartifact
== ART_I_M_GONNA_CRUSH_YA_
) tmp
+= 4;
2814 if (bmwride(ART_ZIN_BA
)) tmp
+= 4;
2815 if (obj
&& obj
->oartifact
== ART_BLOHIT
) tmp
+= 10;
2816 if (obj
&& obj
->oartifact
== ART_KLUEUEUEU
) tmp
+= 1000;
2817 if (uarm
&& uarm
->oartifact
== ART_I_AM_YOUR_FALL
) tmp
+= 10;
2818 if (uarmg
&& uarmg
->oartifact
== ART_GET_THE_OLD_VALUES_BACK
) tmp
+= 3;
2819 if (uleft
&& uleft
->oartifact
== ART_CERBERUS_BAND
) tmp
+= 3;
2820 if (uright
&& uright
->oartifact
== ART_CERBERUS_BAND
) tmp
+= 3;
2821 if (uleft
&& uleft
->oartifact
== ART_CHERRYTAPPER
) tmp
+= 10;
2822 if (uright
&& uright
->oartifact
== ART_CHERRYTAPPER
) tmp
+= 10;
2823 if (uarmc
&& uarmc
->oartifact
== ART_ISHITA_S_OVERWHELMING
) tmp
+= 5;
2824 if (uarmg
&& uarmg
->oartifact
== ART_DOCHGOGRAP
) tmp
+= 4;
2825 if (u
.ulevel
>= 8) tmp
++;
2826 if (u
.ulevel
>= 16) tmp
++;
2827 if (u
.ulevel
>= 24) tmp
++;
2828 if (u
.ulevel
>= 30) tmp
++;
2830 if (uleft
&& uleft
->oartifact
== ART_KRATSCHEM_HARD
) tmp
+= 3;
2831 if (uright
&& uright
->oartifact
== ART_KRATSCHEM_HARD
) tmp
+= 3;
2833 if (PlayerInWedgeHeels
&& !PlayerCannotUseSkills
) {
2834 switch (P_SKILL(P_WEDGE_HEELS
)) {
2836 case P_BASIC
: tmp
+= 1; break;
2837 case P_SKILLED
: tmp
+= 2; break;
2838 case P_EXPERT
: tmp
+= 3; break;
2839 case P_MASTER
: tmp
+= 4; break;
2840 case P_GRAND_MASTER
: tmp
+= 5; break;
2841 case P_SUPREME_MASTER
: tmp
+= 6; break;
2845 if (uwep
&& uwep
->oartifact
== ART_AK_____
) {
2846 if (!PlayerCannotUseSkills
) {
2847 if (P_SKILL(P_FIREARM
) < P_BASIC
) tmp
+= 6;
2848 else if (P_SKILL(P_FIREARM
) == P_BASIC
) tmp
+= 4;
2849 else if (P_SKILL(P_FIREARM
) == P_SKILLED
) tmp
+= 2;
2851 if (P_SKILL(P_FIREARM
) == P_MASTER
) tmp
-= 2;
2852 if (P_SKILL(P_FIREARM
) == P_GRAND_MASTER
) tmp
-= 4;
2853 if (P_SKILL(P_FIREARM
) == P_SUPREME_MASTER
) tmp
-= 6;
2855 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_AK_____
) {
2856 if (P_SKILL(P_FIREARM
) == P_MASTER
) tmp
-= 2;
2857 if (P_SKILL(P_FIREARM
) == P_GRAND_MASTER
) tmp
-= 4;
2858 if (P_SKILL(P_FIREARM
) == P_SUPREME_MASTER
) tmp
-= 6;
2861 if (obj
&& obj
->oartifact
== ART_WASHINGTON_S_CAPPER
) tmp
-= 5;
2862 if (uwep
&& uwep
->oartifact
== ART_LONGLOSS
) tmp
-= rnd(10);
2863 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_LONGLOSS
) tmp
-= rnd(10);
2864 if (uwep
&& uwep
->oartifact
== ART_ENEMY_DEAD_AT_CLOSE_RANGE
) tmp
-= 10;
2865 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_ENEMY_DEAD_AT_CLOSE_RANGE
) tmp
-= 10;
2866 if (uwep
&& uwep
->oartifact
== ART_ITALY_SI_ES
) tmp
-= rnd(25);
2867 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_ITALY_SI_ES
) tmp
-= rnd(25);
2868 if (uarmc
&& uarmc
->oartifact
== ART_OLD_PERSON_TALK
) tmp
-= 5;
2869 if (uwep
&& uwep
->oartifact
== ART_BLACK_MARK
) tmp
-= 1;
2870 if (uwep
&& uwep
->oartifact
== ART_LOUD_SHITTER
) tmp
-= 7;
2871 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_LOUD_SHITTER
) tmp
-= 7;
2872 if (uwep
&& uwep
->oartifact
== ART_CHINESE_MODEL
) tmp
-= 5;
2873 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_CHINESE_MODEL
) tmp
-= 5;
2874 if (uwep
&& uwep
->oartifact
== ART_XUANLONG
) tmp
-= 5;
2875 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_XUANLONG
) tmp
-= 5;
2876 if (uarm
&& uarm
->oartifact
== ART_POWASPEL
) tmp
-= 3;
2877 if (uwep
&& uwep
->oartifact
== ART_UZ_I
) tmp
-= rnd(10);
2878 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_UZ_I
) tmp
-= rnd(10);
2879 if (uwep
&& uwep
->oartifact
== ART_AR_ARMALYTE
) tmp
-= 2;
2880 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_AR_ARMALYTE
) tmp
-= 2;
2881 if (u
.martialstyle
== MARTIALSTYLE_MUAYTHAI
) tmp
-= 5;
2883 if (uarm
&& uarm
->oartifact
== ART_DAMMIT_PICK_UP
) tmp
-= 5;
2885 if (Role_if(PM_OTAKU
) && uarmc
&& itemhasappearance(uarmc
, APP_FOURCHAN_CLOAK
)) tmp
+= 1;
2887 if (is_grassland(u
.ux
, u
.uy
) && !(uarm
&& uarm
->oartifact
== ART_DORL_TSCH
) && !(uarmf
&& itemhasappearance(uarmf
, APP_GARDEN_SLIPPERS
))) tmp
-= rnd(5);
2889 if (ACURR(A_DEX
) < 2) tmp
-= 5;
2890 else if (ACURR(A_DEX
) < 3) tmp
-= 4;
2891 else if (ACURR(A_DEX
) < 4) tmp
-= 3;
2892 else if (ACURR(A_DEX
) < 6) tmp
-= 2;
2893 else if (ACURR(A_DEX
) < 8) tmp
-= 1;
2894 else if (ACURR(A_DEX
) >= 12) tmp
+= (ACURR(A_DEX
) - 11);
2896 if (tech_inuse(T_STEADY_HAND
)) tmp
+= 5;
2898 if (uarmc
&& uarmc
->oartifact
== ART_ROKKO_CHAN_S_SUIT
) tmp
+= 5;
2900 if (!issoviet
&& !rn2(20 - (GushLevel
/ 2) )) tmp
+= rnd(GushLevel
);
2902 if (Race_if(PM_ENGCHIP
) && objects
[obj
->otyp
].oc_skill
== P_BOW
) tmp
-= 5;
2903 if (Race_if(PM_ENGCHIP
) && objects
[obj
->otyp
].oc_skill
== -P_BOW
) tmp
-= 5;
2904 if (Race_if(PM_ENGCHIP
) && objects
[obj
->otyp
].oc_skill
== P_CROSSBOW
) tmp
-= 5;
2905 if (Race_if(PM_ENGCHIP
) && objects
[obj
->otyp
].oc_skill
== -P_BOW
) tmp
-= 5;
2906 if (uwep
&& uwep
->oartifact
== ART_KLOBB
) tmp
-= 6;
2907 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_KLOBB
) tmp
-= 6;
2908 if (uwep
&& uwep
->oartifact
== ART_EXCALIPOOR
) tmp
-= 9;
2909 if (u
.twoweap
&& uswapwep
&& uswapwep
->oartifact
== ART_EXCALIPOOR
) tmp
-= 9;
2911 if (Race_if(PM_VIETIS
) && objects
[obj
->otyp
].oc_skill
!= -P_FIREARM
&& objects
[obj
->otyp
].oc_skill
!= P_FIREARM
) tmp
-= rnd(10);
2913 if (Race_if(PM_BOVER
)) {
2914 if (uarm
&& is_metallic(uarm
)) tmp
-= rnd(3);
2915 if (uarmu
&& is_metallic(uarmu
)) tmp
-= rnd(3);
2916 if (uarmc
&& is_metallic(uarmc
)) tmp
-= rnd(3);
2917 if (uarms
&& is_metallic(uarms
)) tmp
-= rnd(3);
2918 if (uarmh
&& is_metallic(uarmh
)) tmp
-= rnd(3);
2919 if (uarmg
&& is_metallic(uarmg
)) tmp
-= rnd(3);
2920 if (uarmf
&& is_metallic(uarmf
)) tmp
-= rnd(3);
2923 /* shooters that have innate to-hit penalty for the player go here; if you're dual-wielding two launchers
2924 * that use the same type of ammo, and the secondary one has such a penalty, it's supposed to be much higher
2925 * than if it was the primary launcher, for balance purposes, since otherwise dual-wielding assault rifles
2926 * would be far better in every way than a heavy MG! --Amy
2927 * annoyingly, nozzle change (artifact lead unloader) has already changed its fire mode at this point... */
2930 if (launcher
&& launcher
->otyp
== HYDRA_BOW
) tmp
-= rnd(8);
2931 if (launcher
&& launcher
->otyp
== WILDHILD_BOW
&& !Role_if(PM_HUSSY
)) tmp
-= rnd(10);
2932 if (launcher
&& launcher
->otyp
== CATAPULT
) {
2934 if (!rn2(2)) tmp
-= rnd(10);
2936 if (launcher
&& launcher
->otyp
== SUBMACHINE_GUN
&& launcher
->altmode
== WP_MODE_AUTO
) tmp
-= rnd(6);
2937 if (launcher
&& launcher
->otyp
== LEAD_UNLOADER
&& launcher
->altmode
== WP_MODE_AUTO
) tmp
-= rnd(6);
2938 if (launcher
&& launcher
->oartifact
== ART_NOZZLE_CHANGE
&& launcher
->altmode
== WP_MODE_SINGLE
) tmp
-= rnd(6);
2939 if (launcher
&& launcher
->otyp
== AUTO_SHOTGUN
&& launcher
->altmode
== WP_MODE_AUTO
) tmp
-= rnd(8);
2940 if (launcher
&& launcher
->otyp
== POWER_CROSSBOW
) tmp
-= rnd(8);
2941 if (launcher
&& launcher
->otyp
== PILE_BUNKER
) tmp
-= rnd(4);
2942 if (launcher
&& launcher
->otyp
== ASSAULT_RIFLE
&& (launcher
->altmode
== WP_MODE_AUTO
|| (launcher
->altmode
== WP_MODE_BURST
&& !rn2(3)) ) ) {
2944 if (!rn2(3)) tmp
-= rnd(5);
2946 if (launcher
&& launcher
->otyp
== STORM_RIFLE
&& (launcher
->altmode
== WP_MODE_AUTO
|| (launcher
->altmode
== WP_MODE_BURST
&& !rn2(3)) ) ) {
2948 if (!rn2(3)) tmp
-= rnd(5);
2950 if (launcher
&& launcher
->otyp
== ARM_BLASTER
) {
2952 if (!rn2(2)) tmp
-= rnd(8);
2954 if (launcher
&& launcher
->otyp
== DEMON_CROSSBOW
&& launcher
->altmode
== WP_MODE_AUTO
) {
2956 if (!rn2(2)) tmp
-= rnd(6);
2958 if (launcher
&& launcher
->otyp
== KALASHNIKOV
&& (launcher
->altmode
== WP_MODE_AUTO
|| (launcher
->altmode
== WP_MODE_BURST
&& !rn2(3)) ) ) {
2960 if (!rn2(2)) tmp
-= rnd(5);
2962 if (launcher
&& launcher
->otyp
== HEAVY_MACHINE_GUN
) {
2964 if (!rn2(2)) tmp
-= rnd(10);
2965 if (!rn2(3)) tmp
-= rnd(10);
2967 if (launcher
&& launcher
->otyp
== PISTOL_PAIR
&& P_RESTRICTED(P_TWO_WEAPON_COMBAT
)) {
2971 if (launcher
&& launcher
->oartifact
== ART_FN_M____PARA
) tmp
-= rnd(15);
2972 if (launcher
&& launcher
->oartifact
== ART_CITYKILLER_COMBAT_SHOTGUN
) tmp
-= rnd(10);
2973 if (launcher
&& launcher
->oartifact
== ART_COLONEL_BASTARD_S_LASER_PI
) tmp
-= rnd(5);
2976 if (!rn2(2)) doubleshot
= FALSE
;
2977 goto inaccurateguns
;
2980 if (Race_if(PM_SWIKNI
)) {
2982 if (obj
->oeroded
) tmp
-= ((obj
->oeroded
) * 2);
2983 if (obj
->oeroded2
) tmp
-= ((obj
->oeroded2
) * 2);
2988 if (tech_inuse(T_UNARMED_FOCUS
)) tmp
-= rnd(20);
2989 if (u
.martialstyle
== MARTIALSTYLE_KUNGFU
) tmp
-= rnd(20);
2991 /* quarterback is highly skilled at shooting small round objects --Amy */
2992 if (Role_if(PM_QUARTERBACK
) && objects
[obj
->otyp
].oc_skill
== -P_SLING
) tmp
+= rn1(5, 5);
2993 if (Role_if(PM_QUARTERBACK
) && objects
[obj
->otyp
].oc_skill
== P_SLING
) tmp
+= rn1(5, 5);
2995 /* let's just add that bonus anyway. --Amy */
2996 if(mon
->mstun
) tmp
+= 2;
2997 if(mon
->mflee
) tmp
+= 2;
2998 if(mon
->msleeping
) tmp
+= 2;
2999 if(!mon
->mcanmove
) tmp
+= 4;
3001 /* Missile weapon skill: without it, you generally have a lower to-hit; with it, you eventually gain positive bonuses --Amy */
3004 if (!(PlayerCannotUseSkills
)) {
3005 switch (P_SKILL(P_MISSILE_WEAPONS
)) {
3007 case P_BASIC
: tmp
+= rnd(2); skillpierce
+= 1; break;
3008 case P_SKILLED
: tmp
+= rnd(3); skillpierce
+= 2; break;
3009 case P_EXPERT
: tmp
+= rnd(5); skillpierce
+= 3; break;
3010 case P_MASTER
: tmp
+= rnd(6); skillpierce
+= 4; break;
3011 case P_GRAND_MASTER
: tmp
+= rnd(8); skillpierce
+= 5; break;
3012 case P_SUPREME_MASTER
: tmp
+= rnd(10); skillpierce
+= 6; break;
3015 if (obj
&& objects
[obj
->otyp
].oc_skill
== -P_FIREARM
) {
3016 switch (P_SKILL(P_GUN_CONTROL
)) {
3018 case P_BASIC
: tmp
+= rnd(2); skillpierce
+= 1; break;
3019 case P_SKILLED
: tmp
+= rnd(4); skillpierce
+= 2; break;
3020 case P_EXPERT
: tmp
+= rnd(6); skillpierce
+= 3; break;
3021 case P_MASTER
: tmp
+= rnd(8); skillpierce
+= 4; break;
3022 case P_GRAND_MASTER
: tmp
+= rnd(10); skillpierce
+= 5; break;
3023 case P_SUPREME_MASTER
: tmp
+= rnd(12); skillpierce
+= 6; break;
3027 switch (P_SKILL(P_DJEM_SO
)) {
3029 case P_BASIC
: tmp
+= 1; break;
3030 case P_SKILLED
: tmp
+= rnd(2); break;
3031 case P_EXPERT
: tmp
+= rnd(3); break;
3032 case P_MASTER
: tmp
+= rnd(4); break;
3033 case P_GRAND_MASTER
: tmp
+= rnd(5); break;
3034 case P_SUPREME_MASTER
: tmp
+= rnd(6); break;
3037 /* shien and djem so are both "form V" so they boost each other --Amy
3038 * reduced monster evasiveness if you've enhanced both */
3039 if (obj
&& is_lightsaber(obj
) && (obj
->lamplit
|| Role_if(PM_SHADOW_JEDI
)) ) {
3040 if (P_SKILL(P_SHIEN
) >= P_BASIC
&& P_SKILL(P_DJEM_SO
) >= P_BASIC
) skillpierce
++;
3041 if (P_SKILL(P_SHIEN
) >= P_SKILLED
&& P_SKILL(P_DJEM_SO
) >= P_SKILLED
) skillpierce
++;
3042 if (P_SKILL(P_SHIEN
) >= P_EXPERT
&& P_SKILL(P_DJEM_SO
) >= P_EXPERT
) skillpierce
++;
3043 if (P_SKILL(P_SHIEN
) >= P_MASTER
&& P_SKILL(P_DJEM_SO
) >= P_MASTER
) skillpierce
++;
3044 if (P_SKILL(P_SHIEN
) >= P_GRAND_MASTER
&& P_SKILL(P_DJEM_SO
) >= P_GRAND_MASTER
) skillpierce
++;
3045 if (P_SKILL(P_SHIEN
) >= P_SUPREME_MASTER
&& P_SKILL(P_DJEM_SO
) >= P_SUPREME_MASTER
) skillpierce
++;
3048 /* polearms and such should get to-hit bonuses from general combat as well, because I want it :D --Amy */
3051 switch (P_SKILL(P_GENERAL_COMBAT
)) {
3053 case P_BASIC
: tmp
+= 1; skillpierce
+= 1; break;
3054 case P_SKILLED
: tmp
+= rnd(2); skillpierce
+= 2; break;
3055 case P_EXPERT
: tmp
+= rnd(3); skillpierce
+= 3; break;
3056 case P_MASTER
: tmp
+= rnd(4); skillpierce
+= 4; break;
3057 case P_GRAND_MASTER
: tmp
+= rnd(5); skillpierce
+= 5; break;
3058 case P_SUPREME_MASTER
: tmp
+= rnd(6); skillpierce
+= 6; break;
3065 if (uwep
&& uwep
->oartifact
== ART_ULTRA_ANNOYANCE
&& pieks
) skillpierce
+= 5;
3067 if (stopevading
) skillpierce
+= rnd(5);
3069 if (Race_if(PM_FRO
) && objects
[obj
->otyp
].oc_skill
== P_AXE
) {
3081 if (u
.tremblingamount
) tmp
-= rnd(u
.tremblingamount
);
3083 if (!rn2(20)) tmp
-= 20; /* catastrophic failure on a "natural 20", similar to D&D --Amy */
3084 if (Race_if(PM_INHERITOR
) && !rn2(100)) tmp
-= 20;
3086 if (Role_if(PM_FAILED_EXISTENCE
) && rn2(2)) tmp
= -100; /* 50% chance of automiss --Amy */
3087 if (uarmc
&& uarmc
->oartifact
== ART_ARTIFICIAL_FAKE_DIFFICULTY
&& !rn2(6)) tmp
= -100;
3089 if (obj
&& obj
->oartifact
== ART_EVASION_BREAK
) goto evasionchancedone
;
3091 /* certain monsters are capable of deflecting projectiles --Amy */
3093 if (!pieks
&& !(gunused
&& rn2(3)) && !(rn2(13) < skillpierce
) ) {
3095 if (verysmall(mon
->data
) && !rn2(4)) {
3097 pline("%s avoids the projectile!", Monnam(mon
));
3099 if (rathersmall(mon
->data
) && !(verysmall(mon
->data
)) && !rn2(10)) {
3101 pline("%s avoids the projectile!", Monnam(mon
));
3103 if (hugemonst(mon
->data
) && !rn2(2) && (mon
->m_lev
> rnd(GushLevel
) ) ) {
3105 pline("%s shrugs off the projectile!", Monnam(mon
));
3107 if (bigmonst(mon
->data
) && !(hugemonst(mon
->data
)) && !rn2(5) && (mon
->m_lev
> rnd(GushLevel
) ) ) {
3109 pline("%s shrugs off the projectile!", Monnam(mon
));
3114 /* certain traits also allow monsters to avoid getting hit */
3116 if (amorphous(mon
->data
) && !rn2(5) && tmp
> -50 && !(rn2(20) < skillpierce
) ) {
3118 pline("%s's amorphous body skillfully dodges the projectile!", Monnam(mon
));
3120 if (noncorporeal(mon
->data
) && rn2(3) && tmp
> -50 && !(rn2(40) < skillpierce
) ) {
3122 pline("%s easily avoids the projectile due to being noncorporeal!", Monnam(mon
));
3124 if (unsolid(mon
->data
) && !rn2(4) && tmp
> -50 && !(rn2(20) < skillpierce
) ) {
3126 pline("%s's unsolid body lets the projectile pass through harmlessly!", Monnam(mon
));
3131 if (FemtrapActiveNatalia
&& !flags
.female
&& spawnswithhammersandal(mon
->data
) && rn2(4)) {
3133 pline("The projectile just passes through %s!", mon_nam(mon
));
3136 if (mon
->data
== &mons
[PM_XXXXXXXXXXXXXXXXXXXX
]) {
3137 if (tmp
> -100) tmp
= -100;
3138 pline("The projectile just passes through %s!", mon_nam(mon
));
3141 if (mon
->data
== &mons
[PM_IDE_BY__
]) {
3142 if (tmp
> -100) tmp
= -100;
3143 pline("The projectile just passes through %s!", mon_nam(mon
));
3146 /* the elder priest uses cheats */
3147 if (swatting_monster(mon
->data
) && rn2(15) && tmp
> -50) {
3149 pline("%s swats the projectile away!", Monnam(mon
));
3152 if (mon
->data
->msound
== MS_BULLETATOR
&& bulletate
&& rn2(4)) {
3154 pline("%s absorbs the projectile!", Monnam(mon
));
3157 if (FemtrapActiveAnnemarie
&& humanoid(mon
->data
) && mon
->female
&& rn2(15) && tmp
> -50) {
3159 pline("%s swats the projectile away!", Monnam(mon
));
3162 if (ecm_monster(mon
->data
) && rn2(15) && tmp
> -50) {
3164 pline("%s uses an ECM system to divert the projectile!", Monnam(mon
));
3167 if (stupidrock
&& tmp
> -50 && !(rn2(25) < skillpierce
) ) {
3168 if (verysmall(mon
->data
) && !rn2(4)) {
3170 pline("%s avoids the projectile!", Monnam(mon
));
3172 if (rathersmall(mon
->data
) && !(verysmall(mon
->data
)) && !rn2(10)) {
3174 pline("%s avoids the projectile!", Monnam(mon
));
3176 if (hugemonst(mon
->data
) && !rn2(2) && (mon
->m_lev
> rnd(GushLevel
) ) ) {
3178 pline("%s shrugs off the projectile!", Monnam(mon
));
3180 if (bigmonst(mon
->data
) && !(hugemonst(mon
->data
)) && !rn2(5) && (mon
->m_lev
> rnd(GushLevel
) ) ) {
3182 pline("%s shrugs off the projectile!", Monnam(mon
));
3184 if (amorphous(mon
->data
) && !rn2(5) && tmp
> -50) {
3186 pline("%s's amorphous body skillfully dodges the projectile!", Monnam(mon
));
3188 if (noncorporeal(mon
->data
) && rn2(3) && tmp
> -50) {
3190 pline("%s easily avoids the projectile due to being noncorporeal!", Monnam(mon
));
3192 if (unsolid(mon
->data
) && !rn2(4) && tmp
> -50) {
3194 pline("%s's unsolid body lets the projectile pass through harmlessly!", Monnam(mon
));
3199 if (MON_WEP(mon
)) { /* shien monster lightsaber form */
3200 struct obj
*monweapon
;
3201 monweapon
= MON_WEP(mon
);
3203 if (is_lightsaber(monweapon
) && tmp
> -50 && monweapon
->lamplit
&& (!rn2(2) || ((mon
->data
->geno
& G_UNIQ
) && !rn2(2)) ) ) {
3205 pline("%s's lightsaber blocks the projectile!", Monnam(mon
));
3211 if (blocker
= (which_armor(mon
, W_ARMS
))) {
3213 shieldblockrate
= shield_block_rate(blocker
);
3214 shieldblockrate
+= 10; /* monsters can simply block better --Amy */
3216 if (blocker
->otyp
== ELVEN_SHIELD
&& is_elf(mon
->data
)) shieldblockrate
+= 5;
3217 if (blocker
->otyp
== URUK_HAI_SHIELD
&& is_orc(mon
->data
)) shieldblockrate
+= 5;
3218 if (blocker
->otyp
== ORCISH_SHIELD
&& is_orc(mon
->data
)) shieldblockrate
+= 5;
3219 if (blocker
->otyp
== ORCISH_GUARD_SHIELD
&& is_orc(mon
->data
)) shieldblockrate
+= 5;
3220 if (blocker
->otyp
== DWARVISH_ROUNDSHIELD
&& is_dwarf(mon
->data
)) shieldblockrate
+= 5;
3222 if (shieldblockrate
&& (blocker
->spe
> 0)) shieldblockrate
+= (blocker
->spe
* 2);
3223 if (blocker
->blessed
) shieldblockrate
+= 5;
3225 if (stupidrock
&& shieldblockrate
) shieldblockrate
*= 2;
3227 if (blocker
->otyp
== BROKEN_SHIELD
) tmp
= 0;
3229 if ((rnd(100) < shieldblockrate
) && tmp
> -50) {
3231 pline("%s's shield deflects your projectile!", Monnam(mon
));
3235 if (Race_if(PM_ENGCHIP
) && !rn2(20) && objects
[obj
->otyp
].oc_skill
== P_BOW
) tmp
= -100;
3236 if (Race_if(PM_ENGCHIP
) && !rn2(20) && objects
[obj
->otyp
].oc_skill
== -P_BOW
) tmp
= -100;
3237 if (Race_if(PM_ENGCHIP
) && !rn2(20) && objects
[obj
->otyp
].oc_skill
== P_CROSSBOW
) tmp
= -100;
3238 if (Race_if(PM_ENGCHIP
) && !rn2(20) && objects
[obj
->otyp
].oc_skill
== -P_BOW
) tmp
= -100;
3240 /* Modify to-hit depending on distance; but keep it sane.
3241 * Polearms get a distance penalty even when wielded; it's
3242 * hard to hit at a distance.
3245 /* Amy edit: ranged combat was way too powerful, I decided to greatly reduce to-hit at long distances.
3246 * Firearms are an exception for two reasons: one, their ammo always breaks; two, some of them (especially rifles)
3247 * are actually meant to be used at range and those that are not (e.g. shotguns) have limited range anyway.
3248 * Crossbows are a bit of a special case: they're potentially the most damaging shooter for which the ammos
3249 * can be re-used, but most types also need a pretty high enchantment value to get any serious multishot,
3250 * and they're also kind of meant to be used at long range, so their to-hit will receive a lesser nerf. */
3252 if (obj
&& obj
->oartifact
== ART_FTS
) tmp
+= distmin(u
.ux
, u
.uy
, mon
->mx
, mon
->my
);
3254 if ( !(launcher
&& ammo_and_launcher(obj
, launcher
) && objects
[launcher
->otyp
].oc_skill
== P_FIREARM
) && (!(launcher
&& ammo_and_launcher(obj
, launcher
) && objects
[launcher
->otyp
].oc_skill
== P_CROSSBOW
&& !rn2(2)) ) ) {
3256 disttmp
= 3 - distmin(u
.ux
, u
.uy
, mon
->mx
, mon
->my
);
3257 if(disttmp
< -4) disttmp
= -4;
3259 if (uarmg
&& uarmg
->oartifact
== ART_SNIPE_EVERYTHING
&& disttmp
< 0) disttmp
= 0;
3263 if ((distmin(u
.ux
, u
.uy
, mon
->mx
, mon
->my
) > 3) && !(uarmg
&& uarmg
->oartifact
== ART_SNIPE_EVERYTHING
) ) {
3265 switch (distmin(u
.ux
, u
.uy
, mon
->mx
, mon
->my
)) {
3296 /* gloves are a hinderance to proper use of bows */
3297 if (uarmg
&& launcher
&& objects
[launcher
->otyp
].oc_skill
== P_BOW
) {
3298 switch (uarmg
->otyp
) {
3299 case GAUNTLETS_OF_POWER
: /* metal */
3302 case GAUNTLETS_OF_FUMBLING
:
3305 case GAUNTLETS_OF_MISFIRING
:
3308 case GAUNTLETS_OF_PANIC
:
3311 case GAUNTLETS_OF_FREE_ACTION
:
3312 case ELVEN_GAUNTLETS
:
3316 case GAUNTLETS_OF_TRUE_AIM
:
3319 case REGULAR_GLOVES
:
3320 case GAUNTLETS_OF_SWIMMING
:
3321 case GAUNTLETS_OF_DEXTERITY
:
3323 default: /* why do we need this impossible message anyway? --Amy */
3324 /*impossible("Unknown type of gloves (%d)", uarmg->otyp);*/
3329 if (obj
&& launcher
&& ammo_and_launcher(obj
, launcher
) && launcher
->otyp
== LASERXBOW
&& launcher
->lamplit
&& launcher
->altmode
) tmp
+= 5;
3331 /* with a lot of luggage, your agility diminishes */
3332 if (near_capacity()) tmp
-= rnd(near_capacity() * 5);
3333 if (u
.utrap
) tmp
-= 5;
3335 if (uarmg
&& itemhasappearance(uarmg
, APP_CLUMSY_GLOVES
)) tmp
-= 3;
3337 if (Race_if(PM_PLAYER_SKELETON
)) tmp
-= rnd(u
.ulevel
); /* lesser nerf than melee, since you also misfire */
3339 tmp
+= omon_adj(mon
, obj
, TRUE
);
3340 if (is_orc(mon
->data
) && maybe_polyd(is_elf(youmonst
.data
),
3343 if (guaranteed_hit
) {
3344 tmp
+= 1000; /* Guaranteed hit */
3347 /* sleeping unicorns don't catch gems */
3348 if (obj
->oclass
== GEM_CLASS
&& is_unicorn(mon
->data
) && !mon
->msleeping
) {
3350 pline("%s catches and drops %s.", Monnam(mon
), the(xname(obj
)));
3353 pline("%s catches %s.", Monnam(mon
), the(xname(obj
)));
3354 return gem_accept(mon
, obj
);
3358 /* don't make game unwinnable if naive player throws artifact
3360 if (quest_arti_hits_leader(obj
, mon
)) {
3361 /* not wakeup(), which angers non-tame monsters */
3363 mon
->mstrategy
&= ~STRAT_WAITMASK
;
3365 if (mon
->mcanmove
) {
3366 pline("%s catches %s.", Monnam(mon
), the(xname(obj
)));
3367 if (mon
->mpeaceful
) {
3368 boolean next2u
= monnear(mon
, u
.ux
, u
.uy
);
3370 finish_quest(obj
); /* acknowledge quest completion */
3371 pline("%s %s %s back to you.", Monnam(mon
),
3372 (next2u
? "hands" : "tosses"), the(xname(obj
)));
3373 if (!next2u
) sho_obj_return_to_u(obj
);
3374 obj
= addinv(obj
); /* back into your inventory */
3375 (void) encumber_msg();
3377 /* angry leader caught it and isn't returning it */
3378 (void) mpickobj(mon
, obj
, FALSE
);
3380 return 1; /* caller doesn't need to place it */
3385 if (!polearming
&& befriend_with_obj(mon
->data
, obj
)) goto befriended
;
3387 if (obj
->oclass
== WEAPON_CLASS
|| obj
->oclass
== BALL_CLASS
|| obj
->oclass
== CHAIN_CLASS
|| obj
->oclass
== VENOM_CLASS
|| is_weptool(obj
) || obj
->oartifact
== ART_KLUEUEUEU
||
3388 obj
->oclass
== GEM_CLASS
) {
3390 if (!ammo_and_launcher(obj
, launcher
)) {
3393 if (!InvertedState
) {
3394 tmp
+= launcher
->spe
- greatest_erosionX(launcher
);
3396 tmp
-= abs(launcher
->spe
);
3397 tmp
-= greatest_erosionX(launcher
);
3399 tmp
+= weapon_hit_bonus(launcher
);
3400 if (launcher
->oartifact
) tmp
+= spec_abon(launcher
, mon
);
3402 * Elves and Samurais are highly trained w/bows,
3403 * especially their own special types of bow.
3404 * Polymorphing won't make you a bow expert.
3406 if ((Race_if(PM_ELF
) || Race_if(PM_PLAYER_MYRKALFR
) || Race_if(PM_DROW
) ||
3407 Role_if(PM_SAMURAI
) || Role_if(PM_ELPH
) || Role_if(PM_TWELPH
)) &&
3408 (!Upolyd
|| your_race(youmonst
.data
)) &&
3409 objects
[launcher
->otyp
].oc_skill
== P_BOW
) {
3411 if ((Race_if(PM_ELF
) || Race_if(PM_PLAYER_MYRKALFR
)) && launcher
->otyp
== ELVEN_BOW
)
3413 /*else */if (Race_if(PM_DROW
) && launcher
->otyp
== DARK_ELVEN_BOW
)
3415 /*else */if (Role_if(PM_ELPH
) && launcher
->otyp
== ELVEN_BOW
)
3417 /*else */if (Role_if(PM_TWELPH
) && launcher
->otyp
== DARK_ELVEN_BOW
)
3419 /*else */if (Role_if(PM_SAMURAI
) && launcher
->otyp
== YUMI
)
3424 if (otyp
== BOOMERANG
|| otyp
== ALU_BOOMERANG
|| otyp
== SILVER_CHAKRAM
|| otyp
== BATARANG
|| otyp
== DARK_BATARANG
) /* arbitrary */
3426 else if (throwing_weapon(obj
)) /* meant to be thrown */
3428 else /* not meant to be thrown */
3430 /* we know we're dealing with a weapon or weptool handled
3431 by WEAPON_SKILLS once ammo objects have been excluded */
3432 tmp
+= weapon_hit_bonus(obj
);
3435 pline("(%i/20)", tmp
);
3438 if (tmp
>= dieroll
) {
3440 if (hmon(mon
,obj
,thrown
?thrown
:3,dieroll
)) { /* mon still alive */
3441 (void) cutworm(mon
, bhitpos
.x
, bhitpos
.y
, obj
);
3443 exercise(A_DEX
, TRUE
);
3445 if (obj
&& obj
->otyp
== LASER_POLE
) {
3447 if (u
.uvaapadturns
>= 4) {
3449 use_skill(P_VAAPAD
, 1);
3453 if (obj
&& obj
->otyp
== LASER_CHAIN
&& !bimanual(obj
) && !uarms
&& !u
.twoweap
) {
3455 if (u
.umakashiturns
>= 4) {
3456 u
.umakashiturns
= 0;
3457 use_skill(P_MAKASHI
, 1);
3461 /* Detonate bolts shot by Hellfire */
3462 if (ammo_and_launcher(obj
, launcher
) &&
3463 (launcher
->oartifact
== ART_HELLFIRE
|| launcher
->oartifact
== ART_EVERCONSUMING_HELLFIRE
|| obj
->oartifact
== ART_BAKUHATSU_SEI_MISAIRU
|| launcher
->oartifact
== ART_UNIDENTIFIED_HELLCAST
|| launcher
->oartifact
== ART_SEVENTH_SCRIPTURE
)) {
3464 if (cansee(bhitpos
.x
,bhitpos
.y
))
3465 pline("%s explodes in a ball of fire!", Doname2(obj
));
3466 else You_hear("an explosion");
3467 explode(bhitpos
.x
, bhitpos
.y
, ZT_SPELL(ZT_FIRE
),
3468 d(2,6), WEAPON_CLASS
, EXPL_FIERY
);
3471 /* projectiles other than magic stones
3472 * sometimes disappear when thrown
3473 * WAC - Spoon always disappears after doing damage
3475 if (((objects
[otyp
].oc_skill
< P_NONE
&&
3476 objects
[otyp
].oc_skill
> -P_BOOMERANG
) ||
3477 ( objects
[otyp
].oc_skill
== P_DAGGER
&& ((obj
->spe
< 1) || (obj
->spe
> 0 && (!rn2(obj
->spe
+ 1) || !rn2(obj
->spe
+ 1))) ) && (!obj
->oartifact
|| !rn2(1000)) ) ||
3478 ( objects
[otyp
].oc_skill
== P_KNIFE
&& ((obj
->spe
< 1) || (obj
->spe
> 0 && (!rn2(obj
->spe
+ 1) || !rn2(obj
->spe
+ 1))) ) && (!obj
->oartifact
|| !rn2(1000)) ) ||
3479 ( objects
[otyp
].oc_skill
== P_SPEAR
&& ((obj
->spe
< 1) || (obj
->spe
> 0 && (!rn2(obj
->spe
+ 1) || !rn2(obj
->spe
+ 1) || !rn2(obj
->spe
+ 1))) ) && (!obj
->oartifact
|| !rn2(1000)) ) ||
3480 ( objects
[otyp
].oc_skill
== P_JAVELIN
&& ((obj
->spe
< 1) || (obj
->spe
> 0 && !rn2(obj
->spe
+ 1)) ) && (!obj
->oartifact
|| !rn2(1000)) ) ||
3482 /* low chance for daggers, knives and spears to disappear --Amy */
3483 (obj
->oclass
== GEM_CLASS
&&
3484 (!objects
[otyp
].oc_magic
|| !rn2(5) ))) /* also low chance for loadstones etc. to disappear */
3485 || (obj
->oartifact
== ART_HOUCHOU
)
3486 /* WAC catch Hellfire */
3487 || (launcher
&& (launcher
->oartifact
== ART_HELLFIRE
|| launcher
->oartifact
== ART_EVERCONSUMING_HELLFIRE
|| obj
->oartifact
== ART_BAKUHATSU_SEI_MISAIRU
|| launcher
->oartifact
== ART_UNIDENTIFIED_HELLCAST
|| launcher
->oartifact
== ART_SEVENTH_SCRIPTURE
)
3488 && is_ammo(obj
) && ammo_and_launcher(obj
, launcher
))
3490 /* we were breaking 2/3 of everything unconditionally.
3491 * we still don't want anything to survive unconditionally,
3492 * but we need ammo to stay around longer on average.
3495 chance
= greatest_erosionX(obj
) - obj
->spe
; /* base chance increased --Amy */
3498 if (chance
== 3) chance
= 2;
3499 else if (chance
== 4) chance
= 3;
3500 else if (chance
== 5) chance
= 3;
3501 else if (chance
> 5) chance
/= 2;
3502 broken
= rn2(chance
);
3503 } else {/* continue to survive longer with better enchantment --Amy */
3504 chance
= 3 + obj
->spe
- greatest_erosionX(obj
);
3505 if (chance
> 3) chance
= 2 + rno(chance
- 2);
3506 if (chance
< 2) chance
= 2; /* fail safe */
3507 if (Race_if(PM_MONGUNG
)) chance
*= 2;
3508 broken
= !rn2(chance
);
3510 if ( objects
[otyp
].oc_skill
== P_DAGGER
)
3511 broken
= !rn2(Race_if(PM_MONGUNG
) ? 80 : 40);
3512 if ( objects
[otyp
].oc_skill
== P_SPEAR
)
3513 broken
= !rn2(Race_if(PM_MONGUNG
) ? 150 : 75);
3514 if ( objects
[otyp
].oc_skill
== P_KNIFE
)
3515 broken
= !rn2(Race_if(PM_MONGUNG
) ? 160 : 80);
3516 if ( objects
[otyp
].oc_skill
== P_JAVELIN
)
3517 broken
= !rn2(Race_if(PM_MONGUNG
) ? 2400 : 1200);
3518 if (obj
->blessed
&& !rnl(6))
3520 /* also save uncursed ones sometimes --Amy */
3521 if (!obj
->blessed
&& !obj
->cursed
&& !rn2(3) && !rnl(6))
3524 if (!(PlayerCannotUseSkills
)) {
3525 switch (P_SKILL(P_MISSILE_WEAPONS
)) {
3527 case P_BASIC
: if (rn2(10) < 1) broken
= 0; break;
3528 case P_SKILLED
: if (rn2(10) < 2) broken
= 0; break;
3529 case P_EXPERT
: if (rn2(10) < 3) broken
= 0; break;
3530 case P_MASTER
: if (rn2(10) < 4) broken
= 0; break;
3531 case P_GRAND_MASTER
: if (rn2(10) < 5) broken
= 0; break;
3532 case P_SUPREME_MASTER
: if (rn2(10) < 6) broken
= 0; break;
3536 /* allow skill to save ammo --Amy */
3538 if (!(PlayerCannotUseSkills
)) {
3540 if (objects
[otyp
].oc_skill
== -P_BOW
&& (P_SKILL(P_BOW
) >= P_BASIC
) && rn2(P_SKILL(P_BOW
)) )
3542 if (objects
[otyp
].oc_skill
== -P_CROSSBOW
&& (P_SKILL(P_CROSSBOW
) >= P_BASIC
) && rn2(P_SKILL(P_CROSSBOW
)) )
3544 if (objects
[otyp
].oc_skill
== -P_SLING
&& (P_SKILL(P_SLING
) >= P_BASIC
) && rn2(P_SKILL(P_SLING
)) )
3546 if (objects
[otyp
].oc_skill
== -P_DART
&& (P_SKILL(P_DART
) >= P_BASIC
) && rn2(P_SKILL(P_DART
)) )
3548 if (objects
[otyp
].oc_skill
== -P_SHURIKEN
&& (P_SKILL(P_SHURIKEN
) >= P_BASIC
) && rn2(P_SKILL(P_SHURIKEN
)) )
3550 if (objects
[otyp
].oc_skill
== P_DAGGER
&& (P_SKILL(P_DAGGER
) >= P_BASIC
) && rn2(P_SKILL(P_DAGGER
)) )
3552 if (objects
[otyp
].oc_skill
== P_SPEAR
&& (P_SKILL(P_SPEAR
) >= P_BASIC
) && rn2(P_SKILL(P_SPEAR
)) )
3554 if (objects
[otyp
].oc_skill
== P_JAVELIN
&& (P_SKILL(P_JAVELIN
) >= P_BASIC
) && rn2(P_SKILL(P_JAVELIN
)) )
3556 if (objects
[otyp
].oc_skill
== P_KNIFE
&& (P_SKILL(P_KNIFE
) >= P_BASIC
) && rn2(P_SKILL(P_KNIFE
)) )
3561 if (objects
[otyp
].oc_skill
== -P_BOW
&& uarm
&& uarm
->oartifact
== ART_WOODSTOCK
&& broken
&& !rn2(2))
3563 if (objects
[otyp
].oc_skill
== -P_SLING
&& uarms
&& uarms
->oartifact
== ART_MISSING_LETTER_D
&& broken
&& rn2(4))
3565 if (objects
[otyp
].oc_material
== MT_MINERAL
&& uarm
&& uarm
->oartifact
== ART_QUARRY
&& broken
&& !rn2(2))
3567 if (uarmc
&& uarmc
->oartifact
== ART_ARABELLA_S_WEAPON_STORAGE
&& broken
&& !rn2(2))
3569 if (Race_if(PM_MACTHEIST
) && objects
[otyp
].oc_skill
== P_SLING
&& broken
&& !rn2(2))
3571 if (Race_if(PM_MACTHEIST
) && objects
[otyp
].oc_skill
== -P_SLING
&& broken
&& !rn2(2))
3574 if (obj
->oartifact
== ART_USE_A_LOT
) {
3575 if (rn2(10)) broken
= 0;
3577 if (obj
->oartifact
== ART_WIUNEW
) {
3578 if (rn2(10)) broken
= 0;
3580 if (obj
->oartifact
== ART_BE_CONSERVED
) {
3581 if (rn2(10)) broken
= 0;
3584 if (objects
[otyp
].oc_material
== MT_BAMBOO
&& broken
&& !rn2(4)) broken
= 0;
3586 if (objects
[otyp
].oc_material
== MT_LEAD
&& broken
&& !rn2(4)) broken
= 0;
3587 if (otyp
== DART_OF_DISINTEGRATION
&& rn2(10) ) broken
= 1;
3589 /* Due to segfaults and stuff when trying to make this work in other functions, I'm just deciding that
3590 * any thoroughly eroded stuff you throw will generally be destroyed much more often. --Amy */
3591 if ((obj
->oeroded
== MAX_ERODE
|| obj
->oeroded2
== MAX_ERODE
) && !rn2(25) && !hard_to_destruct(obj
)) broken
= 1;
3593 /* artifact that sets the mulching rate to exactly 10%, regardless of other calculations */
3594 if (obj
->oartifact
== ART_ACTUALLY_THE_MATTER_COMES_
) {
3595 if (!rn2(10)) broken
= 1;
3599 /* mulch nastytrap: ammo breaks unconditionally no matter what --Amy */
3600 if (MulchBug
|| u
.uprops
[MULCH_BUG
].extrinsic
|| have_mulchstone() || autismweaponcheck(ART_PIN_EM_ONCE
) ) broken
= 1;
3604 check_shop_obj(obj
, bhitpos
.x
,bhitpos
.y
, TRUE
);
3606 * Thrown grenades and explosive ammo used with the
3607 * relevant launcher explode rather than simply
3610 if ((thrown
== 1 || thrown
== 2) && is_grenade(obj
)) {
3611 grenade_explode(obj
, bhitpos
.x
, bhitpos
.y
, TRUE
, 0);
3612 } else if (ammo_and_launcher(obj
, launcher
) && (objects
[obj
->otyp
].oc_dir
& EXPLOSION
)) {
3613 if (cansee(bhitpos
.x
,bhitpos
.y
))
3614 pline("%s explodes in a ball of fire!", Doname2(obj
));
3615 else You_hear("an explosion"); /* Amy note: we do not add an exclamation mark here on purpose */
3617 explode(bhitpos
.x
, bhitpos
.y
, ZT_SPELL(ZT_FIRE
), d(3,8), WEAPON_CLASS
, EXPL_FIERY
);
3618 u
.cnd_gunpowderused
++;
3620 if (obj
&& obj
->otyp
== MINI_NUKE
) fatman_explosion(bhitpos
.x
, bhitpos
.y
, obj
);
3622 obfree(obj
, (struct obj
*)0);
3624 obfree(obj
, (struct obj
*)0);
3625 u
.cnd_ammomulched
++; /* known problem: bullets can also run this code --Amy */
3626 if (RngeMulchingDisplay
|| (uarm
&& uarm
->oartifact
== ART_SEE_THE_MULCH_STATE
) ) Your("projectile has mulched.");
3631 /* ceramic stuff dulls in melee, but we want ceramic missiles to dull too --Amy */
3632 if (obj
&& objects
[obj
->otyp
].oc_material
== MT_CERAMIC
&& !rn2(10) && obj
->spe
> -10) {
3636 if (obj
&& obj
->oartifact
== ART_CHA_SHATTER
&& !rn2(3) && obj
->spe
> -20) {
3640 passive_obj(mon
, obj
, (struct attack
*)0);
3645 } else if (otyp
== HEAVY_IRON_BALL
) {
3646 exercise(A_STR
, TRUE
);
3647 if (tmp
>= dieroll
) {
3648 int was_swallowed
= guaranteed_hit
;
3650 exercise(A_DEX
, TRUE
);
3652 if (!hmon(mon
,obj
,thrown
?thrown
:3,dieroll
)) { /* mon killed */
3653 if (was_swallowed
&& !u
.uswallow
&& obj
== uball
)
3654 return 1; /* already did placebc() */
3660 } else if (otyp
== BOULDER
) {
3661 exercise(A_STR
, TRUE
);
3662 if (tmp
>= dieroll
) {
3663 exercise(A_DEX
, TRUE
);
3665 (void) hmon(mon
, obj
, thrown
? thrown
: 3, dieroll
);
3668 int bouldersplinterchance
= 10;
3669 if (obj
->oartifact
) bouldersplinterchance
*= 10;
3670 if (obj
->cursed
) bouldersplinterchance
/= 2;
3671 if (obj
->blessed
) bouldersplinterchance
*= 3;
3673 if (!PlayerCannotUseSkills
) {
3674 switch (P_SKILL(P_BOULDER_THROWING
)) {
3676 case P_BASIC
: bouldersplinterchance
*= 6; bouldersplinterchance
/= 5; break;
3677 case P_SKILLED
: bouldersplinterchance
*= 7; bouldersplinterchance
/= 5; break;
3678 case P_EXPERT
: bouldersplinterchance
*= 8; bouldersplinterchance
/= 5; break;
3679 case P_MASTER
: bouldersplinterchance
*= 9; bouldersplinterchance
/= 5; break;
3680 case P_GRAND_MASTER
: bouldersplinterchance
*= 10; bouldersplinterchance
/= 5; break;
3681 case P_SUPREME_MASTER
: bouldersplinterchance
*= 11; bouldersplinterchance
/= 5; break;
3685 if (!rn2(bouldersplinterchance
)) {
3686 pline_The("boulder shatters into fragments!");
3695 } else if ((otyp
== EGG
|| otyp
== CREAM_PIE
) &&
3696 (guaranteed_hit
|| ACURR(A_DEX
) > rnd(25) || (tmp
>= rnd(20) && !PlayersRaysAreInaccurate
) )) { /* F this stupidity. Sorry. --Amy */
3699 (void) hmon(mon
, obj
, thrown
?thrown
:3,dieroll
);
3700 if (issegfaulter
&& otyp
== SEGFAULT_VENOM
&& !rn2(5)) { /* segfault panic! */
3701 u
.segfaultpanic
= TRUE
;
3702 } else if (obj
->oartifact
== ART_DO_NOT_THROW_ME
) { /* uh-oh... you really messed up big time there. */
3703 u
.segfaultpanic
= TRUE
;
3706 return 1; /* hmon used it up */
3708 } else if (obj
->oclass
== POTION_CLASS
&&
3709 (guaranteed_hit
|| ACURR(A_DEX
) > rnd(25) || (tmp
>= rnd(20) && !PlayersRaysAreInaccurate
) )) { /* The damn things missed way too often. */
3711 potionhit(mon
, obj
, TRUE
);
3714 } else if (!polearming
&& (befriend_with_obj(mon
->data
, obj
) || (obj
->oclass
== FOOD_CLASS
&& mon
->egotype_domestic
) || (otyp
== KELP_FROND
&& mon
->egotype_petty
) || (mon
->mtame
&& dogfood(mon
, obj
) <= ACCFOOD
)) ) {
3717 if (tamedog(mon
, obj
, FALSE
)) return 1; /* obj is gone */
3719 /* not tmiss(), which angers non-tame monsters */
3720 miss(xname(obj
), mon
);
3722 mon
->mstrategy
&= ~STRAT_WAITMASK
;
3724 } else if (guaranteed_hit
) {
3725 /* this assumes that guaranteed_hit is due to swallowing */
3728 if (obj
->otyp
== CORPSE
&& touch_petrifies(&mons
[obj
->corpsenm
]) && !rn2(4)) {
3729 if (is_animal(u
.ustuck
->data
)) {
3730 minstapetrify(u
.ustuck
, TRUE
);
3731 /* Don't leave a cockatrice corpse available in a statue */
3738 pline("%s into %s %s.",
3739 Tobjnam(obj
, "vanish"), s_suffix(mon_nam(mon
)),
3740 is_animal(u
.ustuck
->data
) ? "entrails" : "currents");
3748 gem_accept(mon
, obj
)
3749 register struct monst
*mon
;
3750 register struct obj
*obj
;
3753 boolean is_buddy
= sgn(mon
->data
->maligntyp
) == sgn(u
.ualign
.type
);
3754 if (mon
->data
== &mons
[PM_MOLOCH_ALIGNED_UNICORN
]) is_buddy
= FALSE
;
3755 boolean is_gem
= objects
[obj
->otyp
].oc_material
== MT_GEMSTONE
;
3757 static NEARDATA
const char nogood
[] = " is not interested in your junk.";
3758 static NEARDATA
const char acceptgift
[] = " accepts your gift.";
3759 static NEARDATA
const char maybeluck
[] = " hesitatingly";
3760 static NEARDATA
const char noluck
[] = " graciously";
3761 static NEARDATA
const char addluck
[] = " gratefully";
3763 strcpy(buf
,Monnam(mon
));
3764 if (!mon
->mfrenzied
) {
3769 /* Luck boosts used to be way too high. Thus I lowered them. --Amy */
3771 /* object properly identified */
3772 if(obj
->dknown
&& objects
[obj
->otyp
].oc_name_known
) {
3775 strcat(buf
,addluck
);
3776 if (!rn2(isfriday
? 10 : issoviet
? 2 : 3)) change_luck(issoviet
? 4 : rnd(4) );
3777 if (issoviet
) pline("Vy, bezuslovno, povezlo, potomu chto eta igra yavlyayetsya nesbalansirovannym, kak chert!");
3779 strcat(buf
,maybeluck
);
3780 if (!rn2(isfriday
? 10 : issoviet
? 3 : 5)) change_luck(issoviet
? 2 : rnd(2) );
3781 if (issoviet
) pline("Kto-to reshil, chto vy dolzhny poluchit' tonny udachi besplatno!");
3787 /* making guesses */
3788 } else if(obj
->onamelth
|| objects
[obj
->otyp
].oc_uname
) {
3791 strcat(buf
,addluck
);
3792 if (!rn2(isfriday
? 10 : issoviet
? 2 : 3)) change_luck(issoviet
? 2 : rnd(2) );
3793 if (issoviet
) pline("Vy, bezuslovno, povezlo, potomu chto eta igra yavlyayetsya nesbalansirovannym, kak chert!");
3795 strcat(buf
,maybeluck
);
3796 if (!rn2(isfriday
? 10 : issoviet
? 3 : 5)) change_luck(issoviet
? 2 : rnd(2) );
3797 if (issoviet
) pline("Kto-to reshil, chto vy dolzhny poluchit' tonny udachi besplatno!");
3803 /* value completely unknown to @ */
3807 strcat(buf
,addluck
);
3808 if (!rn2(isfriday
? 10 : issoviet
? 2 : 3)) change_luck(1);
3810 strcat(buf
,maybeluck
);
3811 if (!rn2(isfriday
? 10 : issoviet
? 3 : 5)) change_luck(1);
3817 strcat(buf
,acceptgift
);
3818 if(*u
.ushops
) check_shop_obj(obj
, mon
->mx
, mon
->my
, TRUE
);
3819 if (!issoviet
&& rn2(2)) (void) mpickobj(mon
, obj
, FALSE
); /* may merge and free obj */
3820 else obfree(obj
, (struct obj
*)0); /* definitely frees obj, nerf by Amy */
3824 if(!Blind
) pline("%s", buf
);
3825 if (!tele_restrict(mon
)) (void) rloc(mon
, FALSE
);
3830 * Comments about the restructuring of the old breaks() routine.
3832 * There are now three distinct phases to object breaking:
3833 * breaktest() - which makes the check/decision about whether the
3834 * object is going to break.
3835 * breakmsg() - which outputs a message about the breakage,
3836 * appropriate for that particular object. Should
3837 * only be called after a positve breaktest().
3838 * on the object and, if it going to be called,
3839 * it must be called before calling breakobj().
3840 * Calling breakmsg() is optional.
3841 * breakobj() - which actually does the breakage and the side-effects
3842 * of breaking that particular object. This should
3843 * only be called after a positive breaktest() on the
3846 * Each of the above routines is currently static to this source module.
3847 * There are two routines callable from outside this source module which
3848 * perform the routines above in the correct sequence.
3850 * hero_breaks() - called when an object is to be broken as a result
3851 * of something that the hero has done. (throwing it,
3853 * breaks() - called when an object is to be broken for some
3854 * reason other than the hero doing something to it.
3858 * The hero causes breakage of an object (throwing, dropping it, etc.)
3859 * Return 0 if the object didn't break, 1 if the object broke.
3862 hero_breaks(obj
, x
, y
, from_invent
)
3864 xchar x
, y
; /* object location (ox, oy may not be right) */
3865 boolean from_invent
; /* thrown or dropped by player; maybe on shop bill */
3867 boolean in_view
= !Blind
;
3868 if (!breaktest(obj
)) return 0;
3869 breakmsg(obj
, in_view
);
3870 breakobj(obj
, x
, y
, TRUE
, from_invent
);
3875 * The object is going to break for a reason other than the hero doing
3877 * Return 0 if the object doesn't break, 1 if the object broke.
3882 xchar x
, y
; /* object location (ox, oy may not be right) */
3884 boolean in_view
= Blind
? FALSE
: cansee(x
, y
);
3886 if (!breaktest(obj
)) return 0;
3887 breakmsg(obj
, in_view
);
3888 breakobj(obj
, x
, y
, FALSE
, FALSE
);
3893 * Unconditionally break an object. Assumes all resistance checks
3894 * and break messages have been delivered prior to getting here.
3897 breakobj(obj
, x
, y
, hero_caused
, from_invent
)
3899 xchar x
, y
; /* object location (ox, oy may not be right) */
3900 boolean hero_caused
; /* is this the hero's fault? */
3901 boolean from_invent
;
3903 if (itemhasappearance(obj
, APP_POTION_RESERVATROL
) && isok(x
, y
)) {
3904 (void) create_gas_cloud(x
, y
, 3+bcsign(obj
), 8+4*bcsign(obj
));
3905 You("smell chemicals.");
3907 if (itemhasappearance(obj
, APP_POTION_NITROGLYCERIN
) && isok(x
, y
)) {
3908 struct obj
*dynamite
;
3909 dynamite
= mksobj_at(STICK_OF_DYNAMITE
, x
, y
, TRUE
, FALSE
, FALSE
);
3911 if (dynamite
->otyp
!= STICK_OF_DYNAMITE
) delobj(dynamite
);
3913 dynamite
->dynamitekaboom
= 1;
3915 dynamite
->owt
= weight(dynamite
);
3916 attach_bomb_blow_timeout(dynamite
, 0, 0);
3924 if (IS_ALTAR(levl
[x
][y
].typ
))
3925 am
= levl
[x
][y
].altarmask
& AM_MASK
;
3928 switch (obj
->oclass
== POTION_CLASS
? POT_WATER
: obj
->otyp
) {
3933 case POT_WATER
: /* really, all potions */
3934 if (obj
->otyp
== POT_OIL
&& obj
->lamplit
) {
3935 splatter_burning_oil(x
,y
);
3936 } else if ((obj
->otyp
== POT_VAMPIRE_BLOOD
||
3937 obj
->otyp
== POT_BLOOD
) &&
3940 /* ALI: If blood is spilt on a lawful or
3941 * neutral altar the effect is similar to
3942 * human sacrifice. There's no effect on
3943 * chaotic or unaligned altars since it is
3944 * not sufficient to summon a demon.
3947 /* Regardless of your race/alignment etc.
3948 * Lawful and neutral gods really _dont_
3949 * like vampire or (presumed) human blood
3952 pline("You'll regret this infamous offense!");
3953 exercise(A_WIS
, FALSE
);
3955 /* curse the lawful/neutral altar */
3956 pline_The("altar is stained with blood.");
3957 if (PlayerHearsSoundEffects
) pline(issoviet
? "Vy nechisto yeretikom, pravoslavnaya tserkov' progonit vas!" : "Klatsch.");
3958 if (!Is_astralevel(&u
.uz
))
3959 levl
[x
][y
].altarmask
= AM_CHAOTIC
;
3961 } else if (distu(x
,y
) <= 2) {
3962 if (!breathless(youmonst
.data
) || haseyes(youmonst
.data
)) {
3963 if (obj
->otyp
!= POT_WATER
) {
3964 if (!breathless(youmonst
.data
))
3965 /* [what about "familiar odor" when known?] */
3966 You("smell a peculiar odor...");
3968 int numeyes
= eyecount(youmonst
.data
);
3970 (numeyes
== 1) ? body_part(EYE
) :
3971 makeplural(body_part(EYE
)),
3972 (numeyes
== 1) ? "s" : "");
3978 /* monster breathing isn't handled... [yet?] */
3981 /* breaking your own eggs is bad luck */
3982 if (hero_caused
&& obj
->spe
&& obj
->corpsenm
>= LOW_PM
)
3983 change_luck((schar
) -min(obj
->quan
, 5L));
3989 check_shop_obj(obj
, x
, y
, TRUE
);
3990 } else if (!obj
->no_charge
&& costly_spot(x
, y
)) {
3991 /* it is assumed that the obj is a floor-object */
3992 char *o_shop
= in_rooms(x
, y
, SHOPBASE
);
3993 struct monst
*shkp
= shop_keeper(*o_shop
);
3995 if (shkp
) { /* (implies *o_shop != '\0') */
3996 static NEARDATA
long lastmovetime
= 0L;
3997 static NEARDATA boolean peaceful_shk
= FALSE
;
3998 /* We want to base shk actions on her peacefulness
3999 at start of this turn, so that "simultaneous"
4000 multiple breakage isn't drastically worse than
4001 single breakage. (ought to be done via ESHK) */
4002 if (moves
!= lastmovetime
)
4003 peaceful_shk
= shkp
->mpeaceful
;
4004 if (stolen_value(obj
, x
, y
, peaceful_shk
, FALSE
, TRUE
) > 0L &&
4005 (*o_shop
!= u
.ushops
[0] || !inside_shop(u
.ux
, u
.uy
)) &&
4006 moves
!= lastmovetime
) make_angry_shk(shkp
, x
, y
);
4007 lastmovetime
= moves
;
4011 if (obj
== uball
) unpunish();
4012 if (obj
== uchain
) unpunish();
4017 * Check to see if obj is going to break, but don't actually break it.
4018 * Return 0 if the object isn't going to break, 1 if it is.
4019 * Amy edit: artifacts no longer completely immune, muahahahaha!
4020 * also, if the item is vitric, artifact versions should have a considerable chance of breaking too
4026 if (is_vitric(obj
)) {
4027 if (obj_resists(obj
, 1, 33)) return 0;
4029 if (obj_resists(obj
, 1, 99)) return 0;
4031 if ((objects
[obj
->otyp
].oc_material
== MT_GLASS
|| objects
[obj
->otyp
].oc_material
== MT_OBSIDIAN
|| is_vitric(obj
)) && (!obj
->oartifact
|| is_vitric(obj
) || !rn2(10)) &&
4032 obj
->oclass
!= GEM_CLASS
)
4034 switch (obj
->oclass
== POTION_CLASS
? POT_WATER
: obj
->otyp
) {
4035 case EXPENSIVE_CAMERA
:
4036 case POT_WATER
: /* really, all potions */
4042 case BLINDING_VENOM
:
4043 case SEGFAULT_VENOM
:
4044 case FAERIE_FLOSS_RHING
:
4052 breakmsg(obj
, in_view
)
4056 const char *to_pieces
;
4059 switch (obj
->oclass
== POTION_CLASS
? POT_WATER
: obj
->otyp
) {
4060 default: /* glass or crystal wand */
4061 if (obj
->oclass
!= WAND_CLASS
)
4062 /*impossible("breaking odd object?");*/
4063 pline(FunnyHallu
? "Shards, lots of shards!" : "An odd object broke!"); /*quartz rings for example*/
4064 case CRYSTAL_PLATE_MAIL
:
4068 case ORB_OF_CHARGING
:
4069 case ORB_OF_ENCHANTMENT
:
4070 case ORB_OF_DESTRUCTION
:
4071 case EXPENSIVE_CAMERA
:
4072 to_pieces
= " into a thousand pieces";
4074 case POT_WATER
: /* really, all potions */
4076 You_hear("%s shatter!", something
);
4078 pline("%s shatter%s%s!", Doname2(obj
),
4079 (obj
->quan
==1) ? "s" : "", to_pieces
);
4086 if (in_view
) pline("What a mess!");
4090 case BLINDING_VENOM
:
4091 case SEGFAULT_VENOM
:
4092 case FAERIE_FLOSS_RHING
:
4102 int range
, odx
, ody
;
4104 long zorks
= obj
->quan
;
4106 register struct monst
*mon
;
4108 if(!u
.dx
&& !u
.dy
&& !u
.dz
) {
4110 u
.ugold
+= obj
->quan
;
4114 You("cannot throw gold at yourself.");
4121 pline(is_animal(u
.ustuck
->data
) ?
4122 "%s in the %s's entrails." : "%s into %s.",
4124 "The gold disappears", mon_nam(u
.ustuck
));
4125 u
.ustuck
->mgold
+= zorks
;
4128 "The money disappears", mon_nam(u
.ustuck
));
4129 add_to_minv(u
.ustuck
, obj
);
4135 if (u
.dz
< 0 && !Is_airlevel(&u
.uz
) &&
4136 !Underwater
&& !Is_waterlevel(&u
.uz
)) {
4137 pline_The("gold hits the %s, then falls back on top of your %s.",
4138 ceiling(u
.ux
,u
.uy
), body_part(HEAD
));
4139 /* some self damage? */
4140 if(uarmh
) pline("Fortunately, you are wearing a helmet!");
4145 /* consistent with range for normal objects */
4146 range
= (int)((ACURRSTR
)/2 - obj
->owt
/40);
4148 /* see if the gold has a place to move into */
4151 if(!ZAP_POS(levl
[odx
][ody
].typ
) || closed_door(odx
, ody
)) {
4155 mon
= bhit(u
.dx
, u
.dy
, range
, THROWN_WEAPON
,
4156 (int (*)(MONST_P
,OBJ_P
))0,
4157 (int (*)(OBJ_P
,OBJ_P
))0,
4162 if (ghitm(mon
, obj
)) /* was it caught? */
4165 if(ship_object(obj
, bhitpos
.x
, bhitpos
.y
, FALSE
))
4171 if(flooreffects(obj
,bhitpos
.x
,bhitpos
.y
,"fall")) return(1);
4173 pline_The("gold hits the %s.", surface(bhitpos
.x
,bhitpos
.y
));
4174 place_object(obj
,bhitpos
.x
,bhitpos
.y
);
4175 if(*u
.ushops
) sellobj(obj
, bhitpos
.x
, bhitpos
.y
);
4177 newsym(bhitpos
.x
,bhitpos
.y
);