00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00022
00023 #include "crogue.h"
00024
00025 static void throw_item(int which_item);
00026 static void thrown_item_effect(item *itm, int monst);
00027
00028
00029 void throw_item_from_menu(void)
00030 {
00031 int which;
00032
00033 if(filter_matches(filter_none)==0)
00034 {
00035 message(gettext("You don't have anything to throw."));
00036 return;
00037 }
00038 message(gettext("Throw what?"));
00039 which = pick_item(filter_none);
00040
00041 if(which<0)
00042 {
00043 message(gettext("Never mind."));
00044 return;
00045 }
00046
00047 throw_item(which);
00048 }
00049
00050
00051 void throw_readied_item(void)
00052 {
00053
00054 int i;
00055 for(i=0; i<PLRINVSIZE; i++)
00056 if(INVENTORY(i).type && ITEMDESC(INVENTORY(i)).spot == 1 && INVENTORY(i).flags & ITEMFLAG_EQUIPPED)
00057 {
00058 throw_item(i);
00059 return;
00060 }
00061
00062 message(gettext("You don't have any ammunition readied."));
00063 }
00064
00065
00066
00067 static void throw_item(int which_item)
00068 {
00069 direction dir;
00070 coord landing;
00071 sint monst;
00072 uint finishlanding = 1;
00073 sint is_launched;
00074 item projectile;
00075 sint tohitmod = 0;
00076 sint range = 8;
00077 sint damage;
00078
00079 projectile = split_item(which_item);
00080
00081 if( get_item_property(&projectile, PROPERTY_LAUNCHER) )
00082 is_launched = 1;
00083 else
00084 is_launched = 0;
00085
00086 if( is_launched &&
00087 !( w->plr.extrinsic[STAT_MISSILES] & get_item_property(&projectile, PROPERTY_LAUNCHER)->launcher ) )
00088 {
00089 if(w->plr.extrinsic[STAT_MISSILES])
00090 message(gettext("You need an appropriate launcher for that ammo."));
00091 else
00092 message(gettext("You need a launcher for that ammo."));
00093 goto abort;
00094 }
00095 if(projectile.flags & ITEMFLAG_EQUIPPED && ITEMDESC(projectile).spot > 1)
00096 {
00097 message(gettext("You can't throw something you're wearing."));
00098 goto abort;
00099 }
00100 apply_all_item_properties(&projectile, PROPERTY_THROWN_EFFECT);
00101 tohitmod = w->plr.extrinsic[STAT_MISSILE_TOHIT] + weapon_skill_attack();
00102 damage = nrandom(w->plr.extrinsic[STAT_MISSILEDAM_MAX], w->plr.extrinsic[STAT_MISSILEDAM_MIN]);
00103 damage += projectile.plus + weapon_skill_damage();
00104 tohitmod += projectile.plus;
00105 tohitmod += w->plr.level*2;
00106
00107 projectile.flags &= ~ITEMFLAG_EQUIPPED;
00108
00109 prompt_dir(gettext("In what direction?"), &dir);
00110
00111 landing = trace_path(w->plr.x, w->plr.y, dir, range);
00112
00113
00114 if(!w->tiledescs[w->t[landing.y][landing.x].type].passable) {
00115 landing.x -= dir.x;
00116 landing.y -= dir.y;
00117 }
00118
00119
00120 monst = monstbytile(landing.x, landing.y);
00121 if(monst != -1) {
00122 #ifdef DEBUG_BALANCE
00123 if(w->debug_mode)
00124 message("(%i,%i)v[%i,%i]{%i/%i}",
00125 tohitmod, damage,
00126 MDESC(monst)->dv, MDESC(monst)->pv,
00127 w->m[monst].hps, MDESC(monst)->hps_max);
00128 #endif
00129 if(plr_attack_monster_roll(monst, tohitmod)) {
00130 message(gettext("The %s hits the %s."), shortitemname(&projectile), monstname(monst));
00131 monst_anger(monst);
00132 monst_takedamage(monst, damage, 0);
00133 thrown_item_effect(&projectile, monst);
00134 } else {
00135 message(gettext("The %s dodges the %s."), monstname(monst), shortitemname(&projectile));
00136 monst_anger(monst);
00137 }
00138 }
00139
00140 if( finishlanding ) {
00141 if( ITEMDESC(projectile).flags & ITEMFLAG_FRAGILE ) {
00142 message(gettext("The %s shatters!"), shortitemname(&projectile));
00143 } else if( (ITEMDESC(projectile).flags & ITEMFLAG_BREAKABLE) && RANGE(max(2, 3 + 2*projectile.plus), 1) == 1 ) {
00144 message(gettext("The %s breaks."), shortitemname(&projectile));
00145 } else {
00146 place_item(&projectile, landing.x, landing.y);
00147 draw_tile(landing.x, landing.y);
00148 }
00149 }
00150
00151 award_mark();
00152 update_player();
00153 timepass(1);
00154 return;
00155
00156 abort:
00157 merge_item(which_item, projectile);
00158 }
00159
00160
00161 static void thrown_item_effect(item *itm, int monst)
00162 {
00163 const item_property_desc *f;
00164 f = get_item_property(itm, PROPERTY_THROW_HIT_EFFECT);
00165 if(!f)
00166 return;
00167 call_throwhitfunc(f->function, monst);
00168 }
00169
00170
00171