Esempio n. 1
0
        /**
         * Wipe an object clean and make it a standard object of the specified kind.
         * Was previous "object_prep", is now a constructor for Object
         */
        public void prep(Object_Kind k, int lev, aspect rand_aspect)
        {
            int flag, x;
            Bitflag flags = new Bitflag(Object_Flag.SIZE);

            // Assign the kind and copy across data
            this.kind = k;
            this.tval = k.tval;
            this.sval = k.sval;
            this.ac = k.ac;
            this.dd = k.dd;
            this.ds = k.ds;
            this.weight = k.weight;

            // Default number
            this.number = 1;

            for(int i = 0; i < pval_flags.Length; i++) {
                pval_flags[i] = new Bitflag(Object_Flag.SIZE);
            }

            // Apply pvals and then copy flags
            for (int i = 0; i < k.num_pvals; i++) {
                flags.copy(k.pval_flags[i]);
                flags.copy(k.pval_flags[i]);
                x = Random.randcalc(k.pval[i], lev, rand_aspect);
                for (flag = flags.next(Bitflag.FLAG_START); flag != Bitflag.FLAG_null; flag = flags.next(flag + 1))
                    add_pval(x, flag);
            }
            if(k.Base != null) {
                flags.copy(k.Base.flags);
            }
            flags.union(k.flags);

            // Assign charges (wands/staves only)
            if (tval == TVal.TV_WAND || tval == TVal.TV_STAFF)
                pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.charge, lev, rand_aspect);

            // Assign flagless pval for food or oil
            if (tval == TVal.TV_FOOD || tval == TVal.TV_POTION || tval == TVal.TV_FLASK)
                pval[Misc.DEFAULT_PVAL] = (short)Random.randcalc(k.pval[Misc.DEFAULT_PVAL], lev, rand_aspect);

            // Default fuel for lamps
            if (tval == TVal.TV_LIGHT) {
                if(sval == SVal.SV_LIGHT_TORCH)
                    timeout = Misc.DEFAULT_TORCH;
                else if(sval == SVal.SV_LIGHT_LANTERN)
                    timeout = Misc.DEFAULT_LAMP;
            }

            // Default magic
            to_h = (short)Random.randcalc(k.to_h, lev, rand_aspect);
            to_d = (short)Random.randcalc(k.to_d, lev, rand_aspect);
            to_a = (short)Random.randcalc(k.to_a, lev, rand_aspect);
        }
Esempio n. 2
0
        /*
         * Calculate the players current "state", taking into account
         * not only race/class intrinsics, but also objects being worn
         * and temporary spell effects.
         *
         * See also calc_mana() and calc_hitpoints().
         *
         * Take note of the new "speed code", in particular, a very strong
         * player will start slowing down as soon as he reaches 150 pounds,
         * but not until he reaches 450 pounds will he be half as fast as
         * a normal kobold.  This both hurts and helps the player, hurts
         * because in the old days a player could just avoid 300 pounds,
         * and helps because now carrying 300 pounds is not very painful.
         *
         * The "weapon" and "bow" do *not* add to the bonuses to hit or to
         * damage, since that would affect non-combat things.  These values
         * are actually added in later, at the appropriate place.
         *
         * If id_only is true, calc_bonuses() will only use the known
         * information of objects; thus it returns what the player _knows_
         * the character state to be.
         */
        void calc_bonuses(Object.Object[] inventory, ref Player_State state, bool id_only)
        {
            Player p_ptr = Player.instance;
            int i, j, hold;

            int extra_blows = 0;
            int extra_shots = 0;
            int extra_might = 0;

            Object.Object o_ptr;

            Bitflag f = new Bitflag(Object_Flag.SIZE);
            Bitflag collect_f = new Bitflag(Object_Flag.SIZE);

            /*** Reset ***/
            state = new Player_State();
            //memset(state, 0, sizeof *state);

            /* Set various defaults */
            state.speed = 110;
            state.num_blows = 100;

            /*** Extract race/class info ***/

            /* Base infravision (purely racial) */
            if(p_ptr.Race == null)
                return;
            state.see_infra = p_ptr.Race.infra;

            /* Base skills */
            for (i = 0; i < (int)Skill.MAX; i++)
                state.skills[i] = (short)(p_ptr.Race.r_skills[i] + p_ptr.Class.c_skills[i]);

            /*** Analyze player ***/

            /* Extract the player flags */
            Player.player_flags(ref collect_f);

            /*** Analyze equipment ***/

            /* Scan the equipment */
            for (i = Misc.INVEN_WIELD; i < Misc.INVEN_TOTAL; i++)
            {
                o_ptr = inventory[i];

                /* Skip non-objects */
                if (o_ptr ==  null || o_ptr.kind == null) continue;

                /* Extract the item flags */
                if (id_only)
                    o_ptr.object_flags_known(ref f);
                else
                    o_ptr.object_flags(ref f);

                collect_f.union(f);

                /* Affect stats */
                if (f.has(Object_Flag.STR.value)) state.stat_add[(int)Stat.Str] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.STR.value)];
                if (f.has(Object_Flag.INT.value)) state.stat_add[(int)Stat.Int] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.INT.value)];
                if (f.has(Object_Flag.WIS.value)) state.stat_add[(int)Stat.Wis] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.WIS.value)];
                if (f.has(Object_Flag.DEX.value)) state.stat_add[(int)Stat.Dex] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.DEX.value)];
                if (f.has(Object_Flag.CON.value)) state.stat_add[(int)Stat.Con] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.CON.value)];
                if (f.has(Object_Flag.CHR.value)) state.stat_add[(int)Stat.Chr] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.CHR.value)];

                /* Affect stealth */
                if (f.has(Object_Flag.STEALTH.value)) state.skills[(int)Skill.STEALTH] +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.STEALTH.value)];

                /* Affect searching ability (factor of five) */
                if (f.has(Object_Flag.SEARCH.value)) state.skills[(int)Skill.SEARCH] +=
                    (short)(o_ptr.pval[o_ptr.which_pval(Object_Flag.SEARCH.value)] * 5);

                /* Affect searching frequency (factor of five) */
                if (f.has(Object_Flag.SEARCH.value)) state.skills[(int)Skill.SEARCH_FREQUENCY] +=
                    (short)(o_ptr.pval[o_ptr.which_pval(Object_Flag.SEARCH.value)] * 5);

                /* Affect infravision */
                if (f.has(Object_Flag.INFRA.value)) state.see_infra +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.INFRA.value)];

                /* Affect digging (factor of 20) */
                if (f.has(Object_Flag.TUNNEL.value)) state.skills[(int)Skill.DIGGING] +=
                    (short)(o_ptr.pval[o_ptr.which_pval(Object_Flag.TUNNEL.value)] * 20);

                /* Affect speed */
                if (f.has(Object_Flag.SPEED.value)) state.speed +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.SPEED.value)];

                /* Affect blows */
                if (f.has(Object_Flag.BLOWS.value)) extra_blows +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.BLOWS.value)];

                /* Affect shots */
                if (f.has(Object_Flag.SHOTS.value)) extra_shots +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.SHOTS.value)];

                /* Affect Might */
                if (f.has(Object_Flag.MIGHT.value)) extra_might +=
                    o_ptr.pval[o_ptr.which_pval(Object_Flag.MIGHT.value)];

                /* Modify the base armor class */
                state.ac += o_ptr.ac;

                /* The base armor class is always known */
                state.dis_ac += o_ptr.ac;

                /* Apply the bonuses to armor class */
                if (!id_only || o_ptr.is_known())
                    state.to_a += o_ptr.to_a;

                /* Apply the mental bonuses to armor class, if known */
                if (o_ptr.defence_plusses_are_visible())
                    state.dis_to_a += o_ptr.to_a;

                /* Hack -- do not apply "weapon" bonuses */
                if (i == Misc.INVEN_WIELD) continue;

                /* Hack -- do not apply "bow" bonuses */
                if (i == Misc.INVEN_BOW) continue;

                /* Apply the bonuses to hit/damage */
                if (!id_only || o_ptr.is_known())
                {
                    state.to_h += o_ptr.to_h;
                    state.to_d += o_ptr.to_d;
                }

                /* Apply the mental bonuses tp hit/damage, if known */
                if (o_ptr.attack_plusses_are_visible())
                {
                    state.dis_to_h += o_ptr.to_h;
                    state.dis_to_d += o_ptr.to_d;
                }
            }

            /*** Update all flags ***/

            for (i = 0; i < Object_Flag.MAX.value; i++)
                if (collect_f.has(i))
                    state.flags.on(i);

            /*** Handle stats ***/

            /* Calculate stats */
            for (i = 0; i < (int)Stat.Max; i++)
            {
                int add, top, use, ind;

                /* Extract modifier */
                add = state.stat_add[i];

                /* Maximize mode */
                if (Option.birth_maximize.value)
                {
                    /* Modify the stats for race/class */
                    add += (p_ptr.Race.r_adj[i] + p_ptr.Class.c_adj[i]);
                }

                /* Extract the new "stat_top" value for the stat */
                top = Birther.modify_stat_value(p_ptr.stat_max[i], add);

                /* Save the new value */
                state.stat_top[i] = (short)top;

                /* Extract the new "stat_use" value for the stat */
                use = Birther.modify_stat_value(p_ptr.stat_cur[i], add);

                /* Save the new value */
                state.stat_use[i] = (short)use;

                /* Values: n/a */
                if (use <= 3) ind = 0;

                /* Values: 3, 4, ..., 18 */
                else if (use <= 18) ind = (use - 3);

                /* Ranges: 18/00-18/09, ..., 18/210-18/219 */
                else if (use <= 18+219) ind = (15 + (use - 18) / 10);

                /* Range: 18/220+ */
                else ind = (37);

                Misc.assert((0 <= ind) && (ind < Misc.STAT_RANGE));

                /* Save the new index */
                state.stat_ind[i] = (short)ind;
            }

            /*** Temporary flags ***/

            /* Apply temporary "stun" */
            if (p_ptr.timed[(int)Timed_Effect.STUN] > 50)
            {
                state.to_h -= 20;
                state.dis_to_h -= 20;
                state.to_d -= 20;
                state.dis_to_d -= 20;
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 8 / 10);
            }
            else if (p_ptr.timed[(int)Timed_Effect.STUN] != 0)
            {
                state.to_h -= 5;
                state.dis_to_h -= 5;
                state.to_d -= 5;
                state.dis_to_d -= 5;
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 9 / 10);
            }

            /* Invulnerability */
            if (p_ptr.timed[(int)Timed_Effect.INVULN] != 0)
            {
                state.to_a += 100;
                state.dis_to_a += 100;
            }

            /* Temporary blessing */
            if (p_ptr.timed[(int)Timed_Effect.BLESSED] != 0)
            {
                state.to_a += 5;
                state.dis_to_a += 5;
                state.to_h += 10;
                state.dis_to_h += 10;
                state.skills[(int)Skill.DEVICE] = (short) (state.skills[(int)Skill.DEVICE] * 105 / 100);
            }

            /* Temporary shield */
            if (p_ptr.timed[(int)Timed_Effect.SHIELD] != 0)
            {
                state.to_a += 50;
                state.dis_to_a += 50;
            }

            /* Temporary stoneskin */
            if (p_ptr.timed[(int)Timed_Effect.STONESKIN] != 0)
            {
                state.to_a += 40;
                state.dis_to_a += 40;
                state.speed -= 5;
            }

            /* Temporary "Hero" */
            if (p_ptr.timed[(int)Timed_Effect.HERO] != 0)
            {
                state.to_h += 12;
                state.dis_to_h += 12;
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 105 / 100);
            }

            /* Temporary "Berserk" */
            if (p_ptr.timed[(int)Timed_Effect.SHERO] != 0)
            {
                state.to_h += 24;
                state.dis_to_h += 24;
                state.to_a -= 10;
                state.dis_to_a -= 10;
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 9 / 10);
            }

            /* Temporary "fast" */
            if (p_ptr.timed[(int)Timed_Effect.FAST] != 0 || p_ptr.timed[(int)Timed_Effect.SPRINT] != 0)
                state.speed += 10;

            /* Temporary "slow" */
            if (p_ptr.timed[(int)Timed_Effect.SLOW] != 0)
                state.speed -= 10;

            /* Temporary infravision boost */
            if (p_ptr.timed[(int)Timed_Effect.SINFRA] != 0)
                state.see_infra += 5;

            /* Terror - this is necessary because TMD_AFRAID already occupies the
             * of_ptr.timed slot for Object_Flag.AFRAID */
            if (p_ptr.timed[(int)Timed_Effect.TERROR] > p_ptr.timed[(int)Timed_Effect.AFRAID])
                p_ptr.timed[(int)Timed_Effect.AFRAID] = p_ptr.timed[(int)Timed_Effect.TERROR];

            if (p_ptr.timed[(int)Timed_Effect.TERROR] != 0)
                state.speed += 5;

            /* Fear can come from item flags too */
            if (p_ptr.check_state(Object_Flag.AFRAID, p_ptr.state.flags))
            {
                state.to_h -= 20;
                state.dis_to_h -= 20;
                state.to_a += 8;
                state.dis_to_a += 8;
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 95 / 100);
            }

            /* Confusion */
            if (p_ptr.timed[(int)Timed_Effect.CONFUSED] != 0)
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 75 / 100);

            /* Amnesia */
            if (p_ptr.timed[(int)Timed_Effect.AMNESIA] != 0)
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 8 / 10);

            /* Poison */
            if (p_ptr.timed[(int)Timed_Effect.POISONED] != 0)
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 95 / 100);

            /* Hallucination */
            if (p_ptr.timed[(int)Timed_Effect.IMAGE] != 0)
                state.skills[(int)Skill.DEVICE] = (short)(state.skills[(int)Skill.DEVICE] * 8 / 10);

            /*** Analyze weight ***/

            /* Extract the current weight (in tenth pounds) */
            j = p_ptr.total_weight;

            /* Extract the "weight limit" (in tenth pounds) */
            i = state.weight_limit();

            /* Apply "encumbrance" from weight */
            if (j > i / 2) state.speed -= (short)((j - (i / 2)) / (i / 10));

            /* Bloating slows the player down (a little) */
            if (p_ptr.food >= Misc.PY_FOOD_MAX) state.speed -= 10;

            /* Searching slows the player down */
            if (p_ptr.searching != 0) state.speed -= 10;

            /* Sanity check on extreme speeds */
            if (state.speed < 0) state.speed = 0;
            if (state.speed > 199) state.speed = 199;

            /*** Apply modifier bonuses ***/

            /* Actual Modifier Bonuses (Un-inflate stat bonuses) */
            state.to_a += (short)((int)(adj_dex_ta[state.stat_ind[(int)Stat.Dex]]) - 128);
            state.to_d += (short)((int)(adj_str_td[state.stat_ind[(int)Stat.Str]]) - 128);
            state.to_h += (short)((int)(adj_dex_th[state.stat_ind[(int)Stat.Dex]]) - 128);
            state.to_h += (short)((int)(adj_str_th[state.stat_ind[(int)Stat.Str]]) - 128);

            /* Displayed Modifier Bonuses (Un-inflate stat bonuses) */
            state.dis_to_a += (short)((int)(adj_dex_ta[state.stat_ind[(int)Stat.Dex]]) - 128);
            state.dis_to_d += (short)((int)(adj_str_td[state.stat_ind[(int)Stat.Str]]) - 128);
            state.dis_to_h += (short)((int)(adj_dex_th[state.stat_ind[(int)Stat.Dex]]) - 128);
            state.dis_to_h += (short)((int)(adj_str_th[state.stat_ind[(int)Stat.Str]]) - 128);

            /*** Modify skills ***/

            /* Affect Skill -- stealth (bonus one) */
            state.skills[(int)Skill.STEALTH] += 1;

            /* Affect Skill -- disarming (DEX and INT) */
            state.skills[(int)Skill.DISARM] += adj_dex_dis[state.stat_ind[(int)Stat.Dex]];
            state.skills[(int)Skill.DISARM] += adj_int_dis[state.stat_ind[(int)Stat.Int]];

            /* Affect Skill -- magic devices (INT) */
            state.skills[(int)Skill.DEVICE] += adj_int_dev[state.stat_ind[(int)Stat.Int]];

            /* Affect Skill -- saving throw (WIS) */
            state.skills[(int)Skill.SAVE] += adj_wis_sav[state.stat_ind[(int)Stat.Wis]];

            /* Affect Skill -- digging (STR) */
            state.skills[(int)Skill.DIGGING] += adj_str_dig[state.stat_ind[(int)Stat.Str]];

            /* Affect Skills (Level, by Class) */
            for (i = 0; i < (int)Skill.MAX; i++)
                state.skills[i] += (short)(p_ptr.Class.x_skills[i] * p_ptr.lev / 10);

            /* Limit Skill -- digging from 1 up */
            if (state.skills[(int)Skill.DIGGING] < 1) state.skills[(int)Skill.DIGGING] = 1;

            /* Limit Skill -- stealth from 0 to 30 */
            if (state.skills[(int)Skill.STEALTH] > 30) state.skills[(int)Skill.STEALTH] = 30;
            if (state.skills[(int)Skill.STEALTH] < 0) state.skills[(int)Skill.STEALTH] = 0;

            /* Apply Skill -- Extract noise from stealth */
            state.noise = (uint)(1L << (30 - state.skills[(int)Skill.STEALTH]));

            /* Obtain the "hold" value */
            hold = adj_str_hold[state.stat_ind[(int)Stat.Str]];

            /*** Analyze current bow ***/

            /* Examine the "current bow" */
            o_ptr = inventory[Misc.INVEN_BOW];

            /* Assume not heavy */
            state.heavy_shoot = false;

            /* It is hard to hold a heavy bow */
            if (hold < o_ptr.weight / 10)
            {
                /* Hard to wield a heavy bow */
                state.to_h += (short)(2 * (hold - o_ptr.weight / 10));
                state.dis_to_h += (short)(2 * (hold - o_ptr.weight / 10));

                /* Heavy Bow */
                state.heavy_shoot = true;
            }

            /* Analyze launcher */
            if (o_ptr.kind != null)
            {
                /* Get to shoot */
                state.num_shots = 1;

                /* Analyze the launcher */
                switch (o_ptr.sval)
                {
                    /* Sling and ammo */
                    case SVal.SV_SLING:
                    {
                        state.ammo_tval = TVal.TV_SHOT;
                        state.ammo_mult = 2;
                        break;
                    }

                    /* Short Bow and Arrow */
                    case SVal.SV_SHORT_BOW:
                    {
                        state.ammo_tval = TVal.TV_ARROW;
                        state.ammo_mult = 2;
                        break;
                    }

                    /* Long Bow and Arrow */
                    case SVal.SV_LONG_BOW:
                    {
                        state.ammo_tval = TVal.TV_ARROW;
                        state.ammo_mult = 3;
                        break;
                    }

                    /* Light Crossbow and Bolt */
                    case SVal.SV_LIGHT_XBOW:
                    {
                        state.ammo_tval = TVal.TV_BOLT;
                        state.ammo_mult = 3;
                        break;
                    }

                    /* Heavy Crossbow and Bolt */
                    case SVal.SV_HEAVY_XBOW:
                    {
                        state.ammo_tval = TVal.TV_BOLT;
                        state.ammo_mult = 4;
                        break;
                    }
                }

                /* Apply special flags */
                if (o_ptr.kind != null && !state.heavy_shoot)
                {
                    /* Extra shots */
                    state.num_shots += (short)extra_shots;

                    /* Extra might */
                    state.ammo_mult += (byte)extra_might;

                    /* Hack -- Rangers love Bows */
                    if (player_has(Misc.PF.EXTRA_SHOT.value) && (state.ammo_tval == TVal.TV_ARROW))
                    {
                        /* Extra shot at level 20 */
                        if (p_ptr.lev >= 20) state.num_shots++;

                        /* Extra shot at level 40 */
                        if (p_ptr.lev >= 40) state.num_shots++;
                    }
                }

                /* Require at least one shot */
                if (state.num_shots < 1) state.num_shots = 1;
            }

            /*** Analyze weapon ***/

            /* Examine the "current weapon" */
            o_ptr = inventory[Misc.INVEN_WIELD];

            /* Assume not heavy */
            state.heavy_wield = false;

            /* It is hard to hold a heavy weapon */
            if (hold < o_ptr.weight / 10)
            {
                /* Hard to wield a heavy weapon */
                state.to_h += (short)(2 * (hold - o_ptr.weight / 10));
                state.dis_to_h += (short)(2 * (hold - o_ptr.weight / 10));

                /* Heavy weapon */
                state.heavy_wield = true;
            }

            /* Non-object means barehanded attacks */
            if (o_ptr.kind == null)
                Misc.assert(o_ptr.weight == 0);

            /* Normal weapons */
            if (!state.heavy_wield)
            {
                /* Calculate number of blows */
                state.num_blows = (short)calc_blows(o_ptr, state, extra_blows);

                /* Boost digging skill by weapon weight */
                state.skills[(int)Skill.DIGGING] += (short)(o_ptr.weight / 10);
            }

            /* Assume okay */
            state.icky_wield = false;

            /* Priest weapon penalty for non-blessed edged weapons */
            if (player_has(Misc.PF.BLESS_WEAPON.value) && !p_ptr.check_state(Object_Flag.BLESSED, p_ptr.state.flags) &&
                ((o_ptr.tval == TVal.TV_SWORD) || (o_ptr.tval == TVal.TV_POLEARM)))
            {
                /* Reduce the real bonuses */
                state.to_h -= 2;
                state.to_d -= 2;

                /* Reduce the mental bonuses */
                state.dis_to_h -= 2;
                state.dis_to_d -= 2;

                /* Icky weapon */
                state.icky_wield = true;
            }

            return;
        }
Esempio n. 3
0
        /*
         * Obtain the flags for an item which are known to the player
         */
        public void object_flags_known(ref Bitflag flags)
        {
            object_flags(ref flags);

            flags.inter(known_flags);

            if (flavor_is_aware())
                flags.union(kind.flags);

            if (ego != null && easy_know())
                flags.union(ego.flags);
        }