Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

src/throw.c

Go to the documentation of this file.
00001 /* {{{
00002  * CalcRogue, a roguelike game for PCs, calculators and PDAs
00003  * Copyright (C) 2003 Jim Babcock
00004  * 
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  * }}} */
00019 // throw.c
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     // FIXME: This should be handled through player_equipment()
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); // Applies ammo effects on player
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; // Unmark ammo as 'readied'
00108     
00109     prompt_dir(gettext("In what direction?"), &dir);
00110     
00111     landing = trace_path(w->plr.x, w->plr.y, dir, range);
00112     
00113     // If a wall was hit, back up one tile to find the contact point
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     // If a monster was hit, hurt it and (maybe) do magical effects
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(); // Undoes ammo effects
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 

Generated on Thu May 20 13:12:11 2004 for CalcRogue by doxygen 1.3.6