/** * 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); }
/* * 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; }
/* * 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); }