Wikia

Wikihack

Source:Mthrowu.c

2,032pages on
this wiki
Talk0

Below is the full text to src/mthrowu.c from NetHack 3.4.3. To link to a particular line, write [[mthrowu.c#line123]], for example.

Top of file Edit

1.    /*	SCCS Id: @(#)mthrowu.c	3.4	2003/05/09	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
5.    #include "hack.h"
6.    
7.    STATIC_DCL int FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int));
8.    
9.    #define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y))
10.   
11.   #define POLE_LIM 5	/* How far monsters can use pole-weapons */
12.   
13.   #ifndef OVLB
14.   
15.   STATIC_DCL const char *breathwep[];
16.   
17.   #else /* OVLB */
18.   
19.   /*
20.    * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
21.    */
22.   STATIC_OVL NEARDATA const char *breathwep[] = {
23.   				"fragments",
24.   				"fire",
25.   				"frost",
26.   				"sleep gas",
27.   				"a disintegration blast",
28.   				"lightning",
29.   				"poison gas",
30.   				"acid",
31.   				"strange breath #8",
32.   				"strange breath #9"
33.   };
34.   

thitu Edit

35.   /* hero is hit by something other than a monster */
36.   int
37.   thitu(tlev, dam, obj, name)
38.   int tlev, dam;
39.   struct obj *obj;
40.   const char *name;	/* if null, then format `obj' */
41.   {
42.   	const char *onm, *knm;
43.   	boolean is_acid;
44.   	int kprefix = KILLED_BY_AN;
45.   	char onmbuf[BUFSZ], knmbuf[BUFSZ];
46.   
47.   	if (!name) {
48.   	    if (!obj) panic("thitu: name & obj both null?");
49.   	    name = strcpy(onmbuf,
50.   			 (obj->quan > 1L) ? doname(obj) : mshot_xname(obj));
51.   	    knm = strcpy(knmbuf, killer_xname(obj));
52.   	    kprefix = KILLED_BY;  /* killer_name supplies "an" if warranted */
53.   	} else {
54.   	    knm = name;
55.   	    /* [perhaps ought to check for plural here to] */
56.   	    if (!strncmpi(name, "the ", 4) ||
57.   		    !strncmpi(name, "an ", 3) ||
58.   		    !strncmpi(name, "a ", 2)) kprefix = KILLED_BY;
59.   	}
60.   	onm = (obj && obj_is_pname(obj)) ? the(name) :
61.   			    (obj && obj->quan > 1L) ? name : an(name);
62.   	is_acid = (obj && obj->otyp == ACID_VENOM);
63.   
64.   	if(u.uac + tlev <= rnd(20)) {
65.   		if(Blind || !flags.verbose) pline("It misses.");
66.   		else You("are almost hit by %s.", onm);
67.   		return(0);
68.   	} else {
69.   		if(Blind || !flags.verbose) You("are hit!");
70.   		else You("are hit by %s%s", onm, exclam(dam));
71.   
72.   		if (obj && objects[obj->otyp].oc_material == SILVER
73.   				&& hates_silver(youmonst.data)) {
74.   			dam += rnd(20);
75.   			pline_The("silver sears your flesh!");
76.   			exercise(A_CON, FALSE);
77.   		}
78.   		if (is_acid && Acid_resistance)
79.   			pline("It doesn't seem to hurt you.");
80.   		else {
81.   			if (is_acid) pline("It burns!");
82.   			if (Half_physical_damage) dam = (dam+1) / 2;
83.   			losehp(dam, knm, kprefix);
84.   			exercise(A_STR, FALSE);
85.   		}
86.   		return(1);
87.   	}
88.   }
89.   

drop_throw Edit

90.   /* Be sure this corresponds with what happens to player-thrown objects in
91.    * dothrow.c (for consistency). --KAA
92.    * Returns 0 if object still exists (not destroyed).
93.    */
94.   
95.   STATIC_OVL int
96.   drop_throw(obj, ohit, x, y)
97.   register struct obj *obj;
98.   boolean ohit;
99.   int x,y;
100.  {
101.  	int retvalu = 1;
102.  	int create;
103.  	struct monst *mtmp;
104.  	struct trap *t;
105.  
106.  	if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS ||
107.  		    (ohit && obj->otyp == EGG))
108.  		create = 0;
109.  	else if (ohit && (is_multigen(obj) || obj->otyp == ROCK))
110.  		create = !rn2(3);
111.  	else create = 1;
112.  
113.  	if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) &&
114.  			(t = t_at(x, y)) && ((t->ttyp == PIT) ||
115.  			(t->ttyp == SPIKED_PIT)))) {
116.  		int objgone = 0;
117.  
118.  		if (down_gate(x, y) != -1)
119.  			objgone = ship_object(obj, x, y, FALSE);
120.  		if (!objgone) {
121.  			if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */
122.  			    place_object(obj, x, y);
123.  			    if (!mtmp && x == u.ux && y == u.uy)
124.  				mtmp = &youmonst;
125.  			    if (mtmp && ohit)
126.  				passive_obj(mtmp, obj, (struct attack *)0);
127.  			    stackobj(obj);
128.  			    retvalu = 0;
129.  			}
130.  		}
131.  	} else obfree(obj, (struct obj*) 0);
132.  	return retvalu;
133.  }
134.  
135.  #endif /* OVLB */
136.  #ifdef OVL1
137.  

ohitmon Edit

138.  /* an object launched by someone/thing other than player attacks a monster;
139.     return 1 if the object has stopped moving (hit or its range used up) */
140.  int
141.  ohitmon(mtmp, otmp, range, verbose)
142.  struct monst *mtmp;	/* accidental target */
143.  struct obj *otmp;	/* missile; might be destroyed by drop_throw */
144.  int range;		/* how much farther will object travel if it misses */
145.  			/* Use -1 to signify to keep going even after hit, */
146.  			/* unless its gone (used for rolling_boulder_traps) */
147.  boolean verbose;  /* give message(s) even when you can't see what happened */
148.  {
149.  	int damage, tmp;
150.  	boolean vis, ismimic;
151.  	int objgone = 1;
152.  
153.  	ismimic = mtmp->m_ap_type && mtmp->m_ap_type != M_AP_MONSTER;
154.  	vis = cansee(bhitpos.x, bhitpos.y);
155.  
156.  	tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE);
157.  	if (tmp < rnd(20)) {
158.  	    if (!ismimic) {
159.  		if (vis) miss(distant_name(otmp, mshot_xname), mtmp);
160.  		else if (verbose) pline("It is missed.");
161.  	    }
162.  	    if (!range) { /* Last position; object drops */
163.  		(void) drop_throw(otmp, 0, mtmp->mx, mtmp->my);
164.  		return 1;
165.  	    }
166.  	} else if (otmp->oclass == POTION_CLASS) {
167.  	    if (ismimic) seemimic(mtmp);
168.  	    mtmp->msleeping = 0;
169.  	    if (vis) otmp->dknown = 1;
170.  	    potionhit(mtmp, otmp, FALSE);
171.  	    return 1;
172.  	} else {
173.  	    damage = dmgval(otmp, mtmp);
174.  	    if (otmp->otyp == ACID_VENOM && resists_acid(mtmp))
175.  		damage = 0;
176.  	    if (ismimic) seemimic(mtmp);
177.  	    mtmp->msleeping = 0;
178.  	    if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage));
179.  	    else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage));
180.  
181.  	    if (otmp->opoisoned && is_poisonable(otmp)) {
182.  		if (resists_poison(mtmp)) {
183.  		    if (vis) pline_The("poison doesn't seem to affect %s.",
184.  				   mon_nam(mtmp));
185.  		} else {
186.  		    if (rn2(30)) {
187.  			damage += rnd(6);
188.  		    } else {
189.  			if (vis) pline_The("poison was deadly...");
190.  			damage = mtmp->mhp;
191.  		    }
192.  		}
193.  	    }
194.  	    if (objects[otmp->otyp].oc_material == SILVER &&
195.  		    hates_silver(mtmp->data)) {
196.  		if (vis) pline_The("silver sears %s flesh!",
197.  				s_suffix(mon_nam(mtmp)));
198.  		else if (verbose) pline("Its flesh is seared!");
199.  	    }
200.  	    if (otmp->otyp == ACID_VENOM && cansee(mtmp->mx,mtmp->my)) {
201.  		if (resists_acid(mtmp)) {
202.  		    if (vis || verbose)
203.  			pline("%s is unaffected.", Monnam(mtmp));
204.  		    damage = 0;
205.  		} else {
206.  		    if (vis) pline_The("acid burns %s!", mon_nam(mtmp));
207.  		    else if (verbose) pline("It is burned!");
208.  		}
209.  	    }
210.  	    mtmp->mhp -= damage;
211.  	    if (mtmp->mhp < 1) {
212.  		if (vis || verbose)
213.  		    pline("%s is %s!", Monnam(mtmp),
214.  			(nonliving(mtmp->data) || !canspotmon(mtmp))
215.  			? "destroyed" : "killed");
216.  		/* don't blame hero for unknown rolling boulder trap */
217.  		if (!flags.mon_moving &&
218.  		    (otmp->otyp != BOULDER || range >= 0 || !otmp->otrapped))
219.  		    xkilled(mtmp,0);
220.  		else mondied(mtmp);
221.  	    }
222.  
223.  	    if (can_blnd((struct monst*)0, mtmp,
224.  		    (uchar)(otmp->otyp == BLINDING_VENOM ? AT_SPIT : AT_WEAP),
225.  		    otmp)) {
226.  		if (vis && mtmp->mcansee)
227.  		    pline("%s is blinded by %s.", Monnam(mtmp), the(xname(otmp)));
228.  		mtmp->mcansee = 0;
229.  		tmp = (int)mtmp->mblinded + rnd(25) + 20;
230.  		if (tmp > 127) tmp = 127;
231.  		mtmp->mblinded = tmp;
232.  	    }
233.  
234.  	    objgone = drop_throw(otmp, 1, bhitpos.x, bhitpos.y);
235.  	    if (!objgone && range == -1) {  /* special case */
236.  		    obj_extract_self(otmp); /* free it for motion again */
237.  		    return 0;
238.  	    }
239.  	    return 1;
240.  	}
241.  	return 0;
242.  }
243.  

m_throw Edit

244.  void
245.  m_throw(mon, x, y, dx, dy, range, obj)
246.  	register struct monst *mon;
247.  	register int x,y,dx,dy,range;		/* direction and range */
248.  	register struct obj *obj;
249.  {
250.  	register struct monst *mtmp;
251.  	struct obj *singleobj;
252.  	char sym = obj->oclass;
253.  	int hitu, blindinc = 0;
254.  
255.  	bhitpos.x = x;
256.  	bhitpos.y = y;
257.  
258.  	if (obj->quan == 1L) {
259.  	    /*
260.  	     * Remove object from minvent.  This cannot be done later on;
261.  	     * what if the player dies before then, leaving the monster
262.  	     * with 0 daggers?  (This caused the infamous 2^32-1 orcish
263.  	     * dagger bug).
264.  	     *
265.  	     * VENOM is not in minvent - it should already be OBJ_FREE.
266.  	     * The extract below does nothing.
267.  	     */
268.  
269.  	    /* not possibly_unwield, which checks the object's */
270.  	    /* location, not its existence */
271.  	    if (MON_WEP(mon) == obj) {
272.  		    setmnotwielded(mon,obj);
273.  		    MON_NOWEP(mon);
274.  	    }
275.  	    obj_extract_self(obj);
276.  	    singleobj = obj;
277.  	    obj = (struct obj *) 0;
278.  	} else {
279.  	    singleobj = splitobj(obj, 1L);
280.  	    obj_extract_self(singleobj);
281.  	}
282.  
283.  	singleobj->owornmask = 0; /* threw one of multiple weapons in hand? */
284.  
285.  	if (singleobj->cursed && (dx || dy) && !rn2(7)) {
286.  	    if(canseemon(mon) && flags.verbose) {
287.  		if(is_ammo(singleobj))
288.  		    pline("%s misfires!", Monnam(mon));
289.  		else
290.  		    pline("%s as %s throws it!",
291.  			  Tobjnam(singleobj, "slip"), mon_nam(mon));
292.  	    }
293.  	    dx = rn2(3)-1;
294.  	    dy = rn2(3)-1;
295.  	    /* check validity of new direction */
296.  	    if (!dx && !dy) {
297.  		(void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
298.  		return;
299.  	    }
300.  	}
301.  
302.  	/* pre-check for doors, walls and boundaries.
303.  	   Also need to pre-check for bars regardless of direction;
304.  	   the random chance for small objects hitting bars is
305.  	   skipped when reaching them at point blank range */
306.  	if (!isok(bhitpos.x+dx,bhitpos.y+dy)
307.  	    || IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
308.  	    || closed_door(bhitpos.x+dx, bhitpos.y+dy)
309.  	    || (levl[bhitpos.x + dx][bhitpos.y + dy].typ == IRONBARS &&
310.  		hits_bars(&singleobj, bhitpos.x, bhitpos.y, 0, 0))) {
311.  	    (void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
312.  	    return;
313.  	}
314.  
315.  	/* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
316.  	 * early to avoid the dagger bug, anyone who modifies this code should
317.  	 * be careful not to use either one after it's been freed.
318.  	 */
319.  	if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
320.  	while(range-- > 0) { /* Actually the loop is always exited by break */
321.  		bhitpos.x += dx;
322.  		bhitpos.y += dy;
323.  		if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
324.  		    if (ohitmon(mtmp, singleobj, range, TRUE))
325.  			break;
326.  		} else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
327.  		    if (multi) nomul(0);
328.  
329.  		    if (singleobj->oclass == GEM_CLASS &&
330.  			    singleobj->otyp <= LAST_GEM+9 /* 9 glass colors */
331.  			    && is_unicorn(youmonst.data)) {
332.  			if (singleobj->otyp > LAST_GEM) {
333.  			    You("catch the %s.", xname(singleobj));
334.  			    You("are not interested in %s junk.",
335.  				s_suffix(mon_nam(mon)));
336.  			    makeknown(singleobj->otyp);
337.  			    dropy(singleobj);
338.  			} else {
339.  			    You("accept %s gift in the spirit in which it was intended.",
340.  				s_suffix(mon_nam(mon)));
341.  			    (void)hold_another_object(singleobj,
342.  				"You catch, but drop, %s.", xname(singleobj),
343.  				"You catch:");
344.  			}
345.  			break;
346.  		    }
347.  		    if (singleobj->oclass == POTION_CLASS) {
348.  			if (!Blind) singleobj->dknown = 1;
349.  			potionhit(&youmonst, singleobj, FALSE);
350.  			break;
351.  		    }
352.  		    switch(singleobj->otyp) {
353.  			int dam, hitv;
354.  			case EGG:
355.  			    if (!touch_petrifies(&mons[singleobj->corpsenm])) {
356.  				impossible("monster throwing egg type %d",
357.  					singleobj->corpsenm);
358.  				hitu = 0;
359.  				break;
360.  			    }
361.  			    /* fall through */
362.  			case CREAM_PIE:
363.  			case BLINDING_VENOM:
364.  			    hitu = thitu(8, 0, singleobj, (char *)0);
365.  			    break;
366.  			default:
367.  			    dam = dmgval(singleobj, &youmonst);
368.  			    hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
369.  			    if (hitv < -4) hitv = -4;
370.  			    if (is_elf(mon->data) &&
371.  				objects[singleobj->otyp].oc_skill == P_BOW) {
372.  				hitv++;
373.  				if (MON_WEP(mon) &&
374.  				    MON_WEP(mon)->otyp == ELVEN_BOW)
375.  				    hitv++;
376.  				if(singleobj->otyp == ELVEN_ARROW) dam++;
377.  			    }
378.  			    if (bigmonst(youmonst.data)) hitv++;
379.  			    hitv += 8 + singleobj->spe;
380.  			    if (dam < 1) dam = 1;
381.  			    hitu = thitu(hitv, dam, singleobj, (char *)0);
382.  		    }
383.  		    if (hitu && singleobj->opoisoned &&
384.  			is_poisonable(singleobj)) {
385.  			char onmbuf[BUFSZ], knmbuf[BUFSZ];
386.  
387.  			Strcpy(onmbuf, xname(singleobj));
388.  			Strcpy(knmbuf, killer_xname(singleobj));
389.  			poisoned(onmbuf, A_STR, knmbuf, -10);
390.  		    }
391.  		    if(hitu &&
392.  		       can_blnd((struct monst*)0, &youmonst,
393.  				(uchar)(singleobj->otyp == BLINDING_VENOM ?
394.  					AT_SPIT : AT_WEAP), singleobj)) {
395.  			blindinc = rnd(25);
396.  			if(singleobj->otyp == CREAM_PIE) {
397.  			    if(!Blind) pline("Yecch!  You've been creamed.");
398.  			    else pline("There's %s sticky all over your %s.",
399.  				       something,
400.  				       body_part(FACE));
401.  			} else if(singleobj->otyp == BLINDING_VENOM) {
402.  			    int num_eyes = eyecount(youmonst.data);
403.  			    /* venom in the eyes */
404.  			    if(!Blind) pline_The("venom blinds you.");
405.  			    else Your("%s sting%s.",
406.  				      (num_eyes == 1) ? body_part(EYE) :
407.  						makeplural(body_part(EYE)),
408.  				      (num_eyes == 1) ? "s" : "");
409.  			}
410.  		    }
411.  		    if (hitu && singleobj->otyp == EGG) {
412.  			if (!Stone_resistance
413.  			    && !(poly_when_stoned(youmonst.data) &&
414.  				 polymon(PM_STONE_GOLEM))) {
415.  			    Stoned = 5;
416.  			    killer = (char *) 0;
417.  			}
418.  		    }
419.  		    stop_occupation();
420.  		    if (hitu || !range) {
421.  			(void) drop_throw(singleobj, hitu, u.ux, u.uy);
422.  			break;
423.  		    }
424.  		} else if (!range	/* reached end of path */
425.  			/* missile hits edge of screen */
426.  			|| !isok(bhitpos.x+dx,bhitpos.y+dy)
427.  			/* missile hits the wall */
428.  			|| IS_ROCK(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
429.  			/* missile hit closed door */
430.  			|| closed_door(bhitpos.x+dx, bhitpos.y+dy)
431.  			/* missile might hit iron bars */
432.  			|| (levl[bhitpos.x+dx][bhitpos.y+dy].typ == IRONBARS &&
433.  			hits_bars(&singleobj, bhitpos.x, bhitpos.y, !rn2(5), 0))
434.  #ifdef SINKS
435.  			/* Thrown objects "sink" */
436.  			|| IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
437.  #endif
438.  								) {
439.  		    if (singleobj) /* hits_bars might have destroyed it */
440.  			(void) drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
441.  		    break;
442.  		}
443.  		tmp_at(bhitpos.x, bhitpos.y);
444.  		delay_output();
445.  	}
446.  	tmp_at(bhitpos.x, bhitpos.y);
447.  	delay_output();
448.  	tmp_at(DISP_END, 0);
449.  
450.  	if (blindinc) {
451.  		u.ucreamed += blindinc;
452.  		make_blinded(Blinded + (long)blindinc, FALSE);
453.  		if (!Blind) Your(vision_clears);
454.  	}
455.  }
456.  
457.  #endif /* OVL1 */
458.  #ifdef OVLB
459.  

m_useup Edit

460.  /* Remove an item from the monster's inventory and destroy it. */
461.  void
462.  m_useup(mon, obj)
463.  struct monst *mon;
464.  struct obj *obj;
465.  {
466.  	if (obj->quan > 1L) {
467.  		obj->quan--;
468.  		obj->owt = weight(obj);
469.  	} else {
470.  		obj_extract_self(obj);
471.  		possibly_unwield(mon, FALSE);
472.  		if (obj->owornmask) {
473.  		    mon->misc_worn_check &= ~obj->owornmask;
474.  		    update_mon_intrinsics(mon, obj, FALSE, FALSE);
475.  		}
476.  		obfree(obj, (struct obj*) 0);
477.  	}
478.  }
479.  
480.  #endif /* OVLB */
481.  #ifdef OVL1
482.  

thrwmu Edit

483.  /* monster attempts ranged weapon attack against player */
484.  void
485.  thrwmu(mtmp)
486.  struct monst *mtmp;
487.  {
488.  	struct obj *otmp, *mwep;
489.  	xchar x, y;
490.  	schar skill;
491.  	int multishot;
492.  	const char *onm;
493.  
494.  	/* Rearranged beginning so monsters can use polearms not in a line */
495.  	if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
496.  	    mtmp->weapon_check = NEED_RANGED_WEAPON;
497.  	    /* mon_wield_item resets weapon_check as appropriate */
498.  	    if(mon_wield_item(mtmp) != 0) return;
499.  	}
500.  
501.  	/* Pick a weapon */
502.  	otmp = select_rwep(mtmp);
503.  	if (!otmp) return;
504.  
505.  	if (is_pole(otmp)) {
506.  	    int dam, hitv;
507.  
508.  	    if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM ||
509.  		    !couldsee(mtmp->mx, mtmp->my))
510.  		return;	/* Out of range, or intervening wall */
511.  
512.  	    if (canseemon(mtmp)) {
513.  		onm = xname(otmp);
514.  		pline("%s thrusts %s.", Monnam(mtmp),
515.  		      obj_is_pname(otmp) ? the(onm) : an(onm));
516.  	    }
517.  
518.  	    dam = dmgval(otmp, &youmonst);
519.  	    hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my);
520.  	    if (hitv < -4) hitv = -4;
521.  	    if (bigmonst(youmonst.data)) hitv++;
522.  	    hitv += 8 + otmp->spe;
523.  	    if (dam < 1) dam = 1;
524.  
525.  	    (void) thitu(hitv, dam, otmp, (char *)0);
526.  	    stop_occupation();
527.  	    return;
528.  	}
529.  
530.  	x = mtmp->mx;
531.  	y = mtmp->my;
532.  	/* If you are coming toward the monster, the monster
533.  	 * should try to soften you up with missiles.  If you are
534.  	 * going away, you are probably hurt or running.  Give
535.  	 * chase, but if you are getting too far away, throw.
536.  	 */
537.  	if (!lined_up(mtmp) ||
538.  		(URETREATING(x,y) &&
539.  			rn2(BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy))))
540.  	    return;
541.  
542.  	skill = objects[otmp->otyp].oc_skill;
543.  	mwep = MON_WEP(mtmp);		/* wielded weapon */
544.  
545.  	/* Multishot calculations */
546.  	multishot = 1;
547.  	if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER ||
548.  		skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) {
549.  	    /* Assumes lords are skilled, princes are expert */
550.  	    if (is_prince(mtmp->data)) multishot += 2;
551.  	    else if (is_lord(mtmp->data)) multishot++;
552.  
553.  	    switch (monsndx(mtmp->data)) {
554.  	    case PM_RANGER:
555.  		    multishot++;
556.  		    break;
557.  	    case PM_ROGUE:
558.  		    if (skill == P_DAGGER) multishot++;
559.  		    break;
560.  	    case PM_NINJA:
561.  	    case PM_SAMURAI:
562.  		    if (otmp->otyp == YA && mwep &&
563.  			mwep->otyp == YUMI) multishot++;
564.  		    break;
565.  	    default:
566.  		break;
567.  	    }
568.  	    /* racial bonus */
569.  	    if ((is_elf(mtmp->data) &&
570.  		    otmp->otyp == ELVEN_ARROW &&
571.  		    mwep && mwep->otyp == ELVEN_BOW) ||
572.  		(is_orc(mtmp->data) &&
573.  		    otmp->otyp == ORCISH_ARROW &&
574.  		    mwep && mwep->otyp == ORCISH_BOW))
575.  		multishot++;
576.  
577.  	    if ((long)multishot > otmp->quan) multishot = (int)otmp->quan;
578.  	    if (multishot < 1) multishot = 1;
579.  	    else multishot = rnd(multishot);
580.  	}
581.  
582.  	if (canseemon(mtmp)) {
583.  	    char onmbuf[BUFSZ];
584.  
585.  	    if (multishot > 1) {
586.  		/* "N arrows"; multishot > 1 implies otmp->quan > 1, so
587.  		   xname()'s result will already be pluralized */
588.  		Sprintf(onmbuf, "%d %s", multishot, xname(otmp));
589.  		onm = onmbuf;
590.  	    } else {
591.  		/* "an arrow" */
592.  		onm = singular(otmp, xname);
593.  		onm = obj_is_pname(otmp) ? the(onm) : an(onm);
594.  	    }
595.  	    m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE;
596.  	    pline("%s %s %s!", Monnam(mtmp),
597.  		  m_shot.s ? "shoots" : "throws", onm);
598.  	    m_shot.o = otmp->otyp;
599.  	} else {
600.  	    m_shot.o = STRANGE_OBJECT;	/* don't give multishot feedback */
601.  	}
602.  
603.  	m_shot.n = multishot;
604.  	for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++)
605.  	    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
606.  		    distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp);
607.  	m_shot.n = m_shot.i = 0;
608.  	m_shot.o = STRANGE_OBJECT;
609.  	m_shot.s = FALSE;
610.  
611.  	nomul(0);
612.  }
613.  
614.  #endif /* OVL1 */
615.  #ifdef OVLB
616.  

spitmu Edit

617.  int
618.  spitmu(mtmp, mattk)		/* monster spits substance at you */
619.  register struct monst *mtmp;
620.  register struct attack *mattk;
621.  {
622.  	register struct obj *otmp;
623.  
624.  	if(mtmp->mcan) {
625.  
626.  	    if(flags.soundok)
627.  		pline("A dry rattle comes from %s throat.",
628.  		                      s_suffix(mon_nam(mtmp)));
629.  	    return 0;
630.  	}
631.  	if(lined_up(mtmp)) {
632.  		switch (mattk->adtyp) {
633.  		    case AD_BLND:
634.  		    case AD_DRST:
635.  			otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
636.  			break;
637.  		    default:
638.  			impossible("bad attack type in spitmu");
639.  				/* fall through */
640.  		    case AD_ACID:
641.  			otmp = mksobj(ACID_VENOM, TRUE, FALSE);
642.  			break;
643.  		}
644.  		if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {
645.  		    if (canseemon(mtmp))
646.  			pline("%s spits venom!", Monnam(mtmp));
647.  		    m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby),
648.  			distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
649.  		    nomul(0);
650.  		    return 0;
651.  		}
652.  	}
653.  	return 0;
654.  }
655.  
656.  #endif /* OVLB */
657.  #ifdef OVL1
658.  

breamu Edit

659.  int
660.  breamu(mtmp, mattk)			/* monster breathes at you (ranged) */
661.  	register struct monst *mtmp;
662.  	register struct attack  *mattk;
663.  {
664.  	/* if new breath types are added, change AD_ACID to max type */
665.  	int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
666.  
667.  	if(lined_up(mtmp)) {
668.  
669.  	    if(mtmp->mcan) {
670.  		if(flags.soundok) {
671.  		    if(canseemon(mtmp))
672.  			pline("%s coughs.", Monnam(mtmp));
673.  		    else
674.  			You_hear("a cough.");
675.  		}
676.  		return(0);
677.  	    }
678.  	    if(!mtmp->mspec_used && rn2(3)) {
679.  
680.  		if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
681.  
682.  		    if(canseemon(mtmp))
683.  			pline("%s breathes %s!", Monnam(mtmp),
684.  			      breathwep[typ-1]);
685.  		    buzz((int) (-20 - (typ-1)), (int)mattk->damn,
686.  			 mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
687.  		    nomul(0);
688.  		    /* breath runs out sometimes. Also, give monster some
689.  		     * cunning; don't breath if the player fell asleep.
690.  		     */
691.  		    if(!rn2(3))
692.  			mtmp->mspec_used = 10+rn2(20);
693.  		    if(typ == AD_SLEE && !Sleep_resistance)
694.  			mtmp->mspec_used += rnd(20);
695.  		} else impossible("Breath weapon %d used", typ-1);
696.  	    }
697.  	}
698.  	return(1);
699.  }
700.  

linedup Edit

701.  boolean
702.  linedup(ax, ay, bx, by)
703.  register xchar ax, ay, bx, by;
704.  {
705.  	tbx = ax - bx;	/* These two values are set for use */
706.  	tby = ay - by;	/* after successful return.	    */
707.  
708.  	/* sometimes displacement makes a monster think that you're at its
709.  	   own location; prevent it from throwing and zapping in that case */
710.  	if (!tbx && !tby) return FALSE;
711.  
712.  	if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
713.  	   && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
714.  	    if(ax == u.ux && ay == u.uy) return((boolean)(couldsee(bx,by)));
715.  	    else if(clear_path(ax,ay,bx,by)) return TRUE;
716.  	}
717.  	return FALSE;
718.  }
719.  

lined_up Edit

720.  boolean
721.  lined_up(mtmp)		/* is mtmp in position to use ranged attack? */
722.  	register struct monst *mtmp;
723.  {
724.  	return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
725.  }
726.  
727.  #endif /* OVL1 */
728.  #ifdef OVL0
729.  

m_carrying Edit

730.  /* Check if a monster is carrying a particular item.
731.   */
732.  struct obj *
733.  m_carrying(mtmp, type)
734.  struct monst *mtmp;
735.  int type;
736.  {
737.  	register struct obj *otmp;
738.  
739.  	for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
740.  		if(otmp->otyp == type)
741.  			return(otmp);
742.  	return((struct obj *) 0);
743.  }
744.  

hits_bars Edit

745.  /* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
746.  boolean
747.  hits_bars(obj_p, x, y, always_hit, whodidit)
748.  struct obj **obj_p;	/* *obj_p will be set to NULL if object breaks */
749.  int x, y;
750.  int always_hit;	/* caller can force a hit for items which would fit through */
751.  int whodidit;	/* 1==hero, 0=other, -1==just check whether it'll pass thru */
752.  {
753.      struct obj *otmp = *obj_p;
754.      int obj_type = otmp->otyp;
755.      boolean hits = always_hit;
756.  
757.      if (!hits)
758.  	switch (otmp->oclass) {
759.  	case WEAPON_CLASS:
760.  	    {
761.  		int oskill = objects[obj_type].oc_skill;
762.  
763.  		hits = (oskill != -P_BOW  && oskill != -P_CROSSBOW &&
764.  			oskill != -P_DART && oskill != -P_SHURIKEN &&
765.  			oskill != P_SPEAR && oskill != P_JAVELIN &&
766.  			oskill != P_KNIFE);	/* but not dagger */
767.  		break;
768.  	    }
769.  	case ARMOR_CLASS:
770.  		hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
771.  		break;
772.  	case TOOL_CLASS:
773.  		hits = (obj_type != SKELETON_KEY &&
774.  			obj_type != LOCK_PICK &&
775.  #ifdef TOURIST
776.  			obj_type != CREDIT_CARD &&
777.  #endif
778.  			obj_type != TALLOW_CANDLE &&
779.  			obj_type != WAX_CANDLE &&
780.  			obj_type != LENSES &&
781.  			obj_type != TIN_WHISTLE &&
782.  			obj_type != MAGIC_WHISTLE);
783.  		break;
784.  	case ROCK_CLASS:	/* includes boulder */
785.  		if (obj_type != STATUE ||
786.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
787.  		break;
788.  	case FOOD_CLASS:
789.  		if (obj_type == CORPSE &&
790.  			mons[otmp->corpsenm].msize > MZ_TINY) hits = TRUE;
791.  		else
792.  		    hits = (obj_type == MEAT_STICK ||
793.  			    obj_type == HUGE_CHUNK_OF_MEAT);
794.  		break;
795.  	case SPBOOK_CLASS:
796.  	case WAND_CLASS:
797.  	case BALL_CLASS:
798.  	case CHAIN_CLASS:
799.  		hits = TRUE;
800.  		break;
801.  	default:
802.  		break;
803.  	}
804.  
805.      if (hits && whodidit != -1) {
806.  	if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
807.  	    *obj_p = otmp = 0;		/* object is now gone */
808.  	    /* breakage makes its own noises */
809.  	else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
810.  	    pline("Whang!");
811.  	else if (otmp->oclass == COIN_CLASS ||
812.  		objects[obj_type].oc_material == GOLD ||
813.  		objects[obj_type].oc_material == SILVER)
814.  	    pline("Clink!");
815.  	else
816.  	    pline("Clonk!");
817.      }
818.  
819.      return hits;
820.  }
821.  
822.  #endif /* OVL0 */
823.  
824.  /*mthrowu.c*/

Around Wikia's network

Random Wiki