Пример #1
0
        /**
         * This is a helper function used by do_cmd_throw and do_cmd_fire.
         *
         * It abstracts out the projectile path, display code, identify and clean up
         * logic, while using the 'attack' parameter to do work particular to each
         * kind of attack.
         */
        public static void ranged_helper(int item, int dir, int range, int shots, ranged_attack attack)
        {
            /* Get the ammo */
            Object.Object o_ptr = Object.Object.object_from_item_idx(item);

            int          i, j;
            ConsoleColor missile_attr = o_ptr.object_attr();
            char         missile_char = o_ptr.object_char();

            //object_type object_type_body;
            Object.Object i_ptr = new Object.Object();            //&object_type_body;

            //char o_name[80];
            string o_name;

            int           path_n;
            List <ushort> path_g = new List <ushort>();          //[256];

            int msec = Player.Player_Other.instance.delay_factor;

            /* Start at the player */
            int x = Misc.p_ptr.px;
            int y = Misc.p_ptr.py;

            /* Predict the "target" location */
            short ty = (short)(y + 99 * Misc.ddy[dir]);
            short tx = (short)(x + 99 * Misc.ddx[dir]);

            bool hit_target = false;

            /* Check for target validity */
            if ((dir == 5) && Target.okay())
            {
                int taim;
                //char msg[80];
                string msg;
                Target.get(out tx, out ty);
                taim = Cave.distance(y, x, ty, tx);
                if (taim > range)
                {
                    msg = String.Format("Target out of range by {0} squares. Fire anyway? ", taim - range);
                    if (!Utilities.get_check(msg))
                    {
                        return;
                    }
                }
            }

            /* Sound */
            //sound(MSG_SHOOT); //later

            o_ptr.notice_on_firing();

            /* Describe the object */
            o_name = o_ptr.object_desc(Object.Object.Detail.FULL | Object.Object.Detail.SINGULAR);

            /* Actually "fire" the object -- Take a partial turn */
            Misc.p_ptr.energy_use = (short)(100 / shots);

            /* Calculate the path */
            path_n = Cave.project_path(out path_g, range, y, x, ty, tx, 0);

            /* Hack -- Handle stuff */
            Misc.p_ptr.handle_stuff();

            /* Start at the player */
            x = Misc.p_ptr.px;
            y = Misc.p_ptr.py;

            /* Project along the path */
            for (i = 0; i < path_n; ++i)
            {
                int ny = Cave.GRID_Y(path_g[i]);
                int nx = Cave.GRID_X(path_g[i]);

                /* Hack -- Stop before hitting walls */
                if (!Cave.cave_floor_bold(ny, nx))
                {
                    break;
                }

                /* Advance */
                x = nx;
                y = ny;

                /* Only do visuals if the player can "see" the missile */
                if (Cave.player_can_see_bold(y, x))
                {
                    Cave.print_rel(missile_char, missile_attr, y, x);
                    Cave.move_cursor_relative(y, x);

                    Term.fresh();
                    if (Misc.p_ptr.redraw != 0)
                    {
                        Misc.p_ptr.redraw_stuff();
                    }

                    Term.xtra(TERM_XTRA.DELAY, msec);
                    Cave.cave_light_spot(Cave.cave, y, x);

                    Term.fresh();
                    if (Misc.p_ptr.redraw != 0)
                    {
                        Misc.p_ptr.redraw_stuff();
                    }
                }
                else
                {
                    /* Delay anyway for consistency */
                    Term.xtra(TERM_XTRA.DELAY, msec);
                }

                /* Handle monster */
                if (Cave.cave.m_idx[y][x] > 0)
                {
                    break;
                }
            }

            /* Try the attack on the monster at (x, y) if any */
            if (Cave.cave.m_idx[y][x] > 0)
            {
                Monster.Monster m_ptr   = Cave.cave_monster(Cave.cave, Cave.cave.m_idx[y][x]);
                Monster_Race    r_ptr   = Misc.r_info[m_ptr.r_idx];
                bool            visible = m_ptr.ml;

                bool fear = false;
                //char m_name[80];
                string m_name;
                string note_dies = r_ptr.monster_is_unusual() ? " is destroyed." : " dies.";

                attack_result result   = attack(o_ptr, y, x);
                int           dmg      = result.dmg;
                Message_Type  msg_type = result.msg_type;
                string        hit_verb = result.hit_verb;

                if (result.success)
                {
                    hit_target = true;

                    /* Get "the monster" or "it" */
                    m_name = m_ptr.monster_desc(0);

                    o_ptr.notice_attack_plusses();

                    /* No negative damage; change verb if no damage done */
                    if (dmg <= 0)
                    {
                        dmg      = 0;
                        hit_verb = "fail to harm";
                    }

                    if (!visible)
                    {
                        /* Invisible monster */
                        Utilities.msgt(Message_Type.MSG_SHOOT_HIT, "The {0} finds a mark.", o_name);
                    }
                    else
                    {
                        /* Visible monster */
                        if ((Message_Type)msg_type == Message_Type.MSG_SHOOT_HIT)
                        {
                            Utilities.msgt(Message_Type.MSG_SHOOT_HIT, "The {0} {1} {2}.", o_name, hit_verb, m_name);
                        }
                        else if ((Message_Type)msg_type == Message_Type.MSG_HIT_GOOD)
                        {
                            Utilities.msgt(Message_Type.MSG_HIT_GOOD, "The {0} {1} {2}. {3}", o_name, hit_verb, m_name,
                                           "It was a good hit!");
                        }
                        else if ((Message_Type)msg_type == Message_Type.MSG_HIT_GREAT)
                        {
                            Utilities.msgt(Message_Type.MSG_HIT_GREAT, "The {0} {1} {2}. {3}", o_name, hit_verb, m_name,
                                           "It was a great hit!");
                        }
                        else if ((Message_Type)msg_type == Message_Type.MSG_HIT_SUPERB)
                        {
                            Utilities.msgt(Message_Type.MSG_HIT_SUPERB, "The {0} {1} {2}. {3}", o_name, hit_verb, m_name,
                                           "It was a superb hit!");
                        }

                        /* Track this monster */
                        if (m_ptr.ml)
                        {
                            Cave.monster_race_track(m_ptr.r_idx);
                        }
                        if (m_ptr.ml)
                        {
                            Cave.health_track(Misc.p_ptr, Cave.cave.m_idx[y][x]);
                        }
                    }

                    /* Complex message */
                    if (Misc.p_ptr.wizard)
                    {
                        Utilities.msg("You do {0} (out of {1}) damage.", dmg, m_ptr.hp);
                    }

                    /* Hit the monster, check for death */
                    if (!Monster_Make.mon_take_hit(Cave.cave.m_idx[y][x], dmg, ref fear, note_dies))
                    {
                        Monster_Message.message_pain(Cave.cave.m_idx[y][x], dmg);
                        if (fear && m_ptr.ml)
                        {
                            Monster_Message.add_monster_message(m_name, Cave.cave.m_idx[y][x], MON_MSG.FLEE_IN_TERROR, true);
                        }
                    }
                }
            }

            /* Obtain a local object */
            i_ptr = o_ptr.copy();
            i_ptr.split(o_ptr, 1);

            /* See if the ammunition broke or not */
            j = i_ptr.breakage_chance(hit_target);

            /* Drop (or break) near that location */
            Object.Object.drop_near(Cave.cave, i_ptr, j, y, x, true);

            if (item >= 0)
            {
                /* The ammo is from the inventory */
                Object.Object.inven_item_increase(item, -1);
                Object.Object.inven_item_describe(item);
                Object.Object.inven_item_optimize(item);
            }
            else
            {
                /* The ammo is from the floor */
                Object.Object.floor_item_increase(0 - item, -1);
                Object.Object.floor_item_optimize(0 - item);
            }
        }
Пример #2
0
        /*
         * Let the floor carry an object, deleting old squelched items if necessary
         */
        public static short floor_carry(Cave c, int y, int x, Object j_ptr)
        {
            int n = 0;

            short o_idx;

            short this_o_idx, next_o_idx = 0;

            /* Scan objects in that grid for combination */
            for (this_o_idx = c.o_idx[y][x]; this_o_idx != 0; this_o_idx = next_o_idx)
            {
                Object o_ptr = byid(this_o_idx);
                if(o_ptr == null)
                    continue;

                /* Get the next object */
                next_o_idx = o_ptr.next_o_idx;

                /* Check for combination */
                if (o_ptr.similar(j_ptr, object_stack_t.OSTACK_FLOOR))
                {
                    /* Combine the items */
                    o_ptr.absorb(j_ptr);

                    /* Result */
                    return (this_o_idx);
                }

                /* Count objects */
                n++;
            }

            /* Option -- disallow stacking */
            if (Option.birth_no_stacking.value && n != 0) return (0);

            /* The stack is already too large */
            if (n >= Misc.MAX_FLOOR_STACK)
            {
                throw new NotImplementedException();
                ///* Squelch the oldest squelched object */
                //short squelch_idx = floor_get_idx_oldest_squelched(y, x);

                //if (squelch_idx)
                //    delete_object_idx(squelch_idx);
                //else
                //    return 0;
            }

            /* Make an object */
            o_idx = o_pop();

            /* Success */
            if (o_idx != 0)
            {
                Object o_ptr;

                /* Get the object */
                o_ptr = byid(o_idx);

                /* Structure Copy */
                o_ptr = j_ptr.copy();

                /* Location */
                o_ptr.iy = (byte)y;
                o_ptr.ix = (byte)x;

                /* Forget monster */
                o_ptr.held_m_idx = 0;

                /* Link the object to the pile */
                o_ptr.next_o_idx = c.o_idx[y][x];

                /* Link the floor to the object */
                c.o_idx[y][x] = o_idx;

                Cave.cave_note_spot(c, y, x);
                Cave.cave_light_spot(c, y, x);
            }

            /* Result */
            return (o_idx);
        }
Пример #3
0
        /*
         * Wield or wear a single item from the pack or floor
         */
        public void wield_item(int item, int slot)
        {
            //If wierd things happen, add o_ptr back as a parameter instead of this

            //Object object_type_body;
            Object i_ptr = new Object();//&object_type_body;

            string fmt;
            //char o_name[80];
            string o_name;

            bool combined_ammo = false;
            bool track_wielded_item = false;
            int num = 1;

            /* If we are stacking ammo in the quiver */
            if (is_ammo())
            {
                num = number;
                combined_ammo = similar(Misc.p_ptr.inventory[slot], object_stack_t.OSTACK_QUIVER);
            }

            /* Take a turn */
            Misc.p_ptr.energy_use = 100;

            /* Obtain local object */
            i_ptr = copy();

            /* Modify quantity */
            i_ptr.number = (byte)num;

            /* Update object_idx if necessary, once object is in slot */
            if (Cave.tracked_object_is(item))
            {
                track_wielded_item = true;
            }

            /* Decrease the item (from the pack) */
            if (item >= 0)
            {
                inven_item_increase(item, -num);
                inven_item_optimize(item);
            }

            /* Decrease the item (from the floor) */
            else
            {
                floor_item_increase(0 - item, -num);
                floor_item_optimize(0 - item);
            }

            /* Get the wield slot */
            //Things might get wonky here. We stop using "this" and start using "o_ptr" form here on.
            Object o_ptr = Misc.p_ptr.inventory[slot];

            if (combined_ammo)
            {
                /* Add the new ammo to the already-quiver-ed ammo */
                o_ptr.absorb(i_ptr);
            }
            else
            {
                /* Take off existing item */
                if (o_ptr.kind != null)
                    inven_takeoff(slot, 255);

                /* If we are wielding ammo we may need to "open" the slot by shifting
                 * later ammo up the quiver; this is because we already called the
                 * inven_item_optimize() function. */
                if (slot >= Misc.QUIVER_START)
                    open_quiver_slot(slot);

                /* Wear the new stuff */
                o_ptr = i_ptr.copy();

                /* Increment the equip counter by hand */
                Misc.p_ptr.equip_cnt++;
            }

            /* Increase the weight */
            Misc.p_ptr.total_weight += i_ptr.weight * num;

            /* Track object if necessary */
            if (track_wielded_item)
            {
                Cave.track_object(slot);
            }

            /* Do any ID-on-wield */
            o_ptr.notice_on_wield();

            /* Where is the item now */
            if (slot == Misc.INVEN_WIELD)
                fmt = "You are wielding {0} ({1}).";
            else if (slot == Misc.INVEN_BOW)
                fmt = "You are shooting with {0} ({1}).";
            else if (slot == Misc.INVEN_LIGHT)
                fmt = "Your light source is {0} ({1}).";
            else if (combined_ammo)
                fmt = "You combine {0} in your quiver ({1}).";
            else if (slot >= Misc.QUIVER_START && slot < Misc.QUIVER_END)
                fmt = "You add {0} to your quiver ({1}).";
            else
                fmt = "You are wearing {0} ({1}).";

            /* Describe the result */
            o_name = o_ptr.object_desc(Detail.PREFIX | Detail.FULL);

            /* Message */
            Utilities.msgt(Message_Type.MSG_WIELD, fmt, o_name, index_to_label(slot));

            /* Cursed! */
            if (Object_Flag.cursed_p(o_ptr.flags))
            {
                /* Warn the player */
                Utilities.msgt(Message_Type.MSG_CURSED, "Oops! It feels deathly cold!");

                /* Sense the object */
                o_ptr.notice_curses();
            }

            /* Save quiver size */
            save_quiver_size(Misc.p_ptr);

            /* See if we have to overflow the pack */
            pack_overflow();

            /* Recalculate bonuses, torch, mana */
            Misc.p_ptr.notice |= Misc.PN_SORT_QUIVER;
            Misc.p_ptr.update |= (Misc.PU_BONUS | Misc.PU_TORCH | Misc.PU_MANA);
            Misc.p_ptr.redraw |= (Misc.PR_INVEN | Misc.PR_EQUIP);
        }
Пример #4
0
        /*
         * Prepare an object `dst` representing `amt` objects,  based on an existing
         * object `src` representing at least `amt` objects.
         *
         * Takes care of the charge redistribution concerns of stacked items.
         */
        public static void copy_amt(ref Object dst, Object src, int amt)
        {
            //this is the dest
            int charge_time = Random.randcalc(src.kind.time, 0, aspect.AVERAGE), max_time;

            /* Get a copy of the object */
            dst = src.copy();

            /* Modify quantity */
            dst.number = (byte)amt;
            dst.note = src.note;

            /*
             * If the item has charges/timeouts, set them to the correct level
             * too. We split off the same amount as distribute_charges.
             */
            if (src.tval == TVal.TV_WAND || src.tval == TVal.TV_STAFF)
            {
                dst.pval[Misc.DEFAULT_PVAL] = (short)(src.pval[Misc.DEFAULT_PVAL] * amt / src.number);
            }

            if (src.tval == TVal.TV_ROD)
            {
                max_time = charge_time * amt;

                if (src.timeout > max_time)
                    dst.timeout = (short)max_time;
                else
                    dst.timeout = src.timeout;
            }
        }