/* Put the autoinscription on an object */ public static int apply_autoinscription(Object.Object o_ptr) { string o_name = ""; //80 string note = get_autoinscription(o_ptr.kind); /* Don't inscribe unaware objects */ if (note == null || note.Length == 0 || !o_ptr.flavor_is_aware()) { return(0); } /* Don't re-inscribe if it's already inscribed */ if (o_ptr.note != null) { return(0); } /* Get an object description */ o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); if (note == null) { o_ptr.note = Quark.Add(note); } else { o_ptr.note = null; } Utilities.msg("You autoinscribe {0}.", o_name); return(1); }
/** * Notice a given special flag on wielded items. * * \param flag is the flag to notice */ public static void wieldeds_notice_flag(Player.Player p, int flag) { int i; /* Sanity check */ if (flag == 0) { return; } /* XXX Eddie need different naming conventions for starting wieldeds at INVEN_WIELD vs INVEN_WIELD+2 */ for (i = Misc.INVEN_WIELD; i < Misc.ALL_INVEN_TOTAL; i++) { Object o_ptr = p.inventory[i]; Bitflag f = new Bitflag(Object_Flag.SIZE); if (o_ptr.kind == null) { continue; } o_ptr.object_flags(ref f); if (f.has(flag) && !o_ptr.known_flags.has(flag)) { //char o_name[80]; string o_name = o_ptr.object_desc(Detail.BASE); /* Notice the flag */ o_ptr.notice_flag(flag); /* XXX Eddie should this go before noticing the flag to avoid learning twice? */ if (EASY_LEARN && o_ptr.is_jewelry()) { /* XXX Eddie EASY_LEARN Possible concern: gets =teleportation just from +2 speed */ o_ptr.flavor_aware(); o_ptr.check_for_ident(); } /* Message */ Object_Flag.flag_message(flag, o_name); } else { /* Notice that flag is absent */ o_ptr.notice_flag(flag); } /* XXX Eddie should not need this, should be done in noticing, but will remove later */ o_ptr.check_for_ident(); } return; }
/** * 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); } }
/* * Buy an object from a store */ static bool store_purchase(int item) { int amt, num; int price; Object.Object o_ptr; //object_type object_type_body; Object.Object i_ptr = new Object.Object(); //char o_name[80]; string o_name; Store store = current_store(); if (store == null) { Utilities.msg("You cannot purchase items when not in a store."); return false; } /* Get the actual object */ o_ptr = store.stock[item]; if (item < 0) return false; /* Clear all current messages */ Term.msg_flag = false; Utilities.prt("", 0, 0); if (store.sidx == STORE.HOME) { amt = o_ptr.number; } else { /* Price of one */ price = price_item(o_ptr, false, 1); /* Check if the player can afford any at all */ if ((uint)Misc.p_ptr.au < (uint)price) { /* Tell the user */ Utilities.msg("You do not have enough gold for this item."); /* Abort now */ return false; } /* Work out how many the player can afford */ amt = Misc.p_ptr.au / price; if (amt > o_ptr.number) amt = o_ptr.number; /* Double check for wands/staves */ if ((Misc.p_ptr.au >= price_item(o_ptr, false, amt+1)) && (amt < o_ptr.number)) amt++; } /* Find the number of this item in the inventory */ if (!o_ptr.flavor_is_aware()) num = 0; else num = find_inven(o_ptr); o_name = String.Format("{0} how many{1}? (max {2}) ", (store.sidx == STORE.HOME) ? "Take" : "Buy", num != 0 ? String.Format(" (you have {0})", num) : "", amt); /* Get a quantity */ amt = Utilities.get_quantity(o_name, amt); /* Allow user abort */ if (amt <= 0) return false; /* Get desired object */ Object.Object.copy_amt(ref i_ptr, o_ptr, amt); /* Ensure we have room */ if (!i_ptr.inven_carry_okay()) { Utilities.msg("You cannot carry that many items."); return false; } /* Describe the object (fully) */ o_name = i_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); /* Attempt to buy it */ if (store.sidx != STORE.HOME) { bool response; /* Extract the price for the entire stack */ price = price_item(i_ptr, false, i_ptr.number); Utilities.screen_save(); /* Show price */ Utilities.prt(String.Format("Price: {0}", price), 1, 0); /* Confirm purchase */ response = store_get_check(String.Format("Buy {0}? [ESC, any other key to accept]", o_name)); Utilities.screen_load(); /* Negative response, so give up */ if (!response) return false; Game_Command.insert(Command_Code.BUY); Game_Command.get_top().set_arg_choice(0, item); Game_Command.get_top().set_arg_number(1, amt); } /* Home is much easier */ else { Game_Command.insert(Command_Code.RETRIEVE); Game_Command.get_top().set_arg_choice(0, item); Game_Command.get_top().set_arg_number(1, amt); } /* Not kicked out */ return true; }
public static void see_floor_items(Game_Event.Event_Type type, Game_Event data, object user) { int py = Misc.p_ptr.py; int px = Misc.p_ptr.px; int floor_num = 0; int[] floor_list = new int[Misc.MAX_FLOOR_STACK + 1]; bool blind = ((Misc.p_ptr.timed[(int)Timed_Effect.BLIND] != 0) || (Cave.no_light())); string p = "see"; int can_pickup = 0; int i; /* Scan all marked objects in the grid */ floor_num = Object.Object.scan_floor(floor_list, floor_list.Length, py, px, 0x03); if (floor_num == 0) { return; } for (i = 0; i < floor_num; i++) { can_pickup += Object.Object.byid((short)floor_list[i]).inven_carry_okay()?1:0; } /* One object */ if (floor_num == 1) { /* Get the object */ Object.Object o_ptr = Object.Object.byid((short)floor_list[0]); //char o_name[80]; string o_name = null; if (can_pickup == 0) { p = "have no room for"; } else if (blind) { p = "feel"; } /* Describe the object. Less detail if blind. */ if (blind) { o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.BASE); } else { o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); } /* Message */ Utilities.message_flush(); Utilities.msg("You {0} {1}.", p, o_name); } else { ui_event e; if (can_pickup == 0) { p = "have no room for the following objects"; } else if (blind) { p = "feel something on the floor"; } throw new NotImplementedException(); /* Display objects on the floor */ //screen_save(); //show_floor(floor_list, floor_num, (OLIST_WEIGHT)); //prt(format("You %s: ", p), 0, 0); ///* Wait for it. Use key as next command. */ //e = inkey_ex(); //Term_event_push(&e); ///* Restore screen */ //screen_load(); } }
/* Put the autoinscription on an object */ public static int apply_autoinscription(Object.Object o_ptr) { string o_name = ""; //80 string note = get_autoinscription(o_ptr.kind); /* Don't inscribe unaware objects */ if (note == null || note.Length == 0 || !o_ptr.flavor_is_aware()) return 0; /* Don't re-inscribe if it's already inscribed */ if (o_ptr.note != null) return 0; /* Get an object description */ o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); if(note == null) o_ptr.note = Quark.Add(note); else o_ptr.note = null; Utilities.msg("You autoinscribe {0}.", o_name); return 1; }
/* * Sense the inventory */ public static void sense_inventory() { int i; //char o_name[80]; string o_name = null; uint rate; /* No ID when confused in a bad state */ if (Misc.p_ptr.timed[(int)Timed_Effect.CONFUSED] != 0) { return; } /* Notice some things after a while */ if (Misc.turn >= (object_last_wield + 3000)) { object_notice_after_time(); object_last_wield = 0; } /* Get improvement rate */ if (Misc.p_ptr.player_has(Misc.PF.PSEUDO_ID_IMPROV.value)) { rate = (uint)(Misc.p_ptr.Class.sense_base / (Misc.p_ptr.lev * Misc.p_ptr.lev + Misc.p_ptr.Class.sense_div)); } else { rate = (uint)(Misc.p_ptr.Class.sense_base / (Misc.p_ptr.lev + Misc.p_ptr.Class.sense_div)); } if (!Random.one_in_((int)rate)) { return; } /* Check everything */ for (i = 0; i < Misc.ALL_INVEN_TOTAL; i++) { string text = null; Object o_ptr = Misc.p_ptr.inventory[i]; obj_pseudo_t feel; bool cursed; bool okay = false; /* Skip empty slots */ if (o_ptr.kind == null) { continue; } /* Valid "tval" codes */ switch (o_ptr.tval) { case TVal.TV_SHOT: case TVal.TV_ARROW: case TVal.TV_BOLT: case TVal.TV_BOW: case TVal.TV_DIGGING: case TVal.TV_HAFTED: case TVal.TV_POLEARM: case TVal.TV_SWORD: case TVal.TV_BOOTS: case TVal.TV_GLOVES: case TVal.TV_HELM: case TVal.TV_CROWN: case TVal.TV_SHIELD: case TVal.TV_CLOAK: case TVal.TV_SOFT_ARMOR: case TVal.TV_HARD_ARMOR: case TVal.TV_DRAG_ARMOR: { okay = true; break; } } /* Skip non-sense machines */ if (!okay) { continue; } /* It is known, no information needed */ if (o_ptr.is_known()) { continue; } /* It has already been sensed, do not sense it again */ if (o_ptr.was_sensed()) { /* Small chance of wielded, sensed items getting complete ID */ if (o_ptr.artifact == null && (i >= Misc.INVEN_WIELD) && Random.one_in_(1000)) { throw new NotImplementedException(); //do_ident_item(i, o_ptr); } continue; } /* Occasional failure on inventory items */ if ((i < Misc.INVEN_WIELD) && Random.one_in_(5)) { continue; } /* Sense the object */ o_ptr.notice_sensing(); cursed = o_ptr.notice_curses(); /* Get the feeling */ feel = o_ptr.pseudo(); /* Stop everything */ Cave.disturb(Misc.p_ptr, 0, 0); if (cursed) { text = "cursed"; } else { text = Misc.inscrip_text[(int)feel]; } o_name = o_ptr.object_desc(Detail.BASE); /* Average pseudo-ID means full ID */ if (feel == obj_pseudo_t.INSCRIP_AVERAGE) { o_ptr.notice_everything(); Utilities.msgt(Message_Type.MSG_PSEUDOID, "You feel the %s (%c) %s %s average...", o_name, index_to_label(i), ((i >= Misc.INVEN_WIELD) ? "you are using" : "in your pack"), ((o_ptr.number == 1) ? "is" : "are")); } else { if (i >= Misc.INVEN_WIELD) { Utilities.msgt(Message_Type.MSG_PSEUDOID, "You feel the %s (%c) you are %s %s %s...", o_name, index_to_label(i), describe_use(i), ((o_ptr.number == 1) ? "is" : "are"), text); } else { Utilities.msgt(Message_Type.MSG_PSEUDOID, "You feel the %s (%c) in your pack %s %s...", o_name, index_to_label(i), ((o_ptr.number == 1) ? "is" : "are"), text); } } /* Set squelch flag as appropriate */ if (i < Misc.INVEN_WIELD) { Misc.p_ptr.notice |= Misc.PN_SQUELCH; } /* Combine / Reorder the pack (later) */ Misc.p_ptr.notice |= (Misc.PN_COMBINE | Misc.PN_REORDER | Misc.PN_SORT_QUIVER); /* Redraw stuff */ Misc.p_ptr.redraw |= (Misc.PR_INVEN | Misc.PR_EQUIP); } }
/* * Identify an item. * * `item` is used to print the slot occupied by an object in equip/inven. * Any negative value assigned to "item" can be used for specifying an object * on the floor. */ public static void do_ident_item(int item, Object.Object o_ptr) { string o_name = ""; //80 Message_Type msg_type = (Message_Type)0; int i; bool bad = true; /* Identify it */ o_ptr.flavor_aware(); o_ptr.notice_everything(); /* Apply an autoinscription, if necessary */ Squelch.apply_autoinscription(o_ptr); /* Set squelch flag */ Misc.p_ptr.notice |= (int)Misc.PN_SQUELCH; /* Recalculate bonuses */ Misc.p_ptr.update |= (Misc.PU_BONUS); /* Combine / Reorder the pack (later) */ Misc.p_ptr.notice |= (int)(Misc.PN_COMBINE | Misc.PN_REORDER | Misc.PN_SORT_QUIVER); /* Window stuff */ Misc.p_ptr.redraw |= (Misc.PR_INVEN | Misc.PR_EQUIP); /* Description */ o_name = o_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); /* Determine the message type. */ /* CC: we need to think more carefully about how we define "bad" with * multiple pvals - currently using "all nonzero pvals < 0" */ for (i = 0; i < o_ptr.num_pvals; i++) { if (o_ptr.pval[i] > 0) { bad = false; } } if (bad) { msg_type = Message_Type.MSG_IDENT_BAD; } else if (o_ptr.artifact != null) { msg_type = Message_Type.MSG_IDENT_ART; } else if (o_ptr.ego != null) { msg_type = Message_Type.MSG_IDENT_EGO; } else { msg_type = Message_Type.MSG_GENERIC; } /* Log artifacts to the history list. */ if (o_ptr.artifact != null) { History.add_artifact(o_ptr.artifact, true, true); } /* Describe */ if (item >= Misc.INVEN_WIELD) { Utilities.msgt(msg_type, "{0}: {1} ({2}).", Object.Object.describe_use(item), o_name, Object.Object.index_to_label(item)); //Utilities.msgt(msg_type, "%^s: %s (%c).", describe_use(item), o_name, index_to_label(item)); } else if (item >= 0) { Utilities.msgt(msg_type, "In your pack: {0} ({1}).", o_name, Object.Object.index_to_label(item)); //Utilities.msgt(msg_type, "In your pack: %s (%c).", o_name, index_to_label(item)); } else { Utilities.msgt(msg_type, "On the ground: {0}.", o_name); } }
/* * Acid has hit the player, attempt to affect some armor. * * Note that the "base armor" of an object never changes. * * If any armor is damaged (or resists), the player takes less damage. */ static bool minus_ac(Player.Player p) { Object.Object o_ptr = null; Bitflag f = new Bitflag(Object.Object_Flag.SIZE); //char o_name[80]; string o_name; /* Avoid crash during monster power calculations */ if (p.inventory == null) { return(false); } /* Pick a (possibly empty) inventory slot */ switch (Random.randint1(6)) { case 1: o_ptr = p.inventory[Misc.INVEN_BODY]; break; case 2: o_ptr = p.inventory[Misc.INVEN_ARM]; break; case 3: o_ptr = p.inventory[Misc.INVEN_OUTER]; break; case 4: o_ptr = p.inventory[Misc.INVEN_HANDS]; break; case 5: o_ptr = p.inventory[Misc.INVEN_HEAD]; break; case 6: o_ptr = p.inventory[Misc.INVEN_FEET]; break; //default: Misc.assert(0); //Nick: DA FUQ is this doing here C??? } /* Nothing to damage */ if (o_ptr.kind == null) { return(false); } /* No damage left to be done */ if (o_ptr.ac + o_ptr.to_a <= 0) { return(false); } /* Describe */ o_name = o_ptr.object_desc(Object.Object.Detail.BASE); //object_desc(o_name, sizeof(o_name), o_ptr, ODESC_BASE); /* Extract the flags */ o_ptr.object_flags(ref f); /* Object resists */ if (f.has(Object.Object_Flag.IGNORE_ACID.value)) { Utilities.msg("Your %s is unaffected!", o_name); return(true); } /* Message */ Utilities.msg("Your %s is damaged!", o_name); /* Damage the item */ o_ptr.to_a--; p.update |= Misc.PU_BONUS; p.redraw |= (Misc.PR_EQUIP); /* Item was damaged */ return(true); }
/* * Let an object fall to the ground at or near a location. * * The initial location is assumed to be "in_bounds_fully()". * * This function takes a parameter "chance". This is the percentage * chance that the item will "disappear" instead of drop. If the object * has been thrown, then this is the chance of disappearance on contact. * * This function will produce a description of a drop event under the player * when "verbose" is true. * * We check several locations to see if we can find a location at which * the object can combine, stack, or be placed. Artifacts will try very * hard to be placed, including "teleporting" to a useful grid if needed. */ public static void drop_near(Cave c, Object j_ptr, int chance, int y, int x, bool verbose) { int i, k, n, d, s; int bs, bn; int by, bx; int dy, dx; int ty, tx; Object o_ptr; //char o_name[80]; string o_name; bool flag = false; bool plural = false; /* Extract plural */ if (j_ptr.number != 1) plural = true; /* Describe object */ o_name = j_ptr.object_desc(Detail.BASE); /* Handle normal "breakage" */ if (j_ptr.artifact == null && (Random.randint0(100) < chance)) { /* Message */ Utilities.msg("The {0} break{1}.", o_name, Misc.PLURAL(plural)); /* Failure */ return; } /* Score */ bs = -1; /* Picker */ bn = 0; /* Default */ by = y; bx = x; /* Scan local grids */ for (dy = -3; dy <= 3; dy++) { /* Scan local grids */ for (dx = -3; dx <= 3; dx++) { bool comb = false; /* Calculate actual distance */ d = (dy * dy) + (dx * dx); /* Ignore distant grids */ if (d > 10) continue; /* Location */ ty = y + dy; tx = x + dx; /* Skip illegal grids */ if (!Cave.cave.in_bounds_fully(ty, tx)) continue; /* Require line of sight */ if (!Cave.los(y, x, ty, tx)) continue; /* Require floor space */ if (Cave.cave.feat[ty][tx] != Cave.FEAT_FLOOR) continue; /* No objects */ k = 0; n = 0; /* Scan objects in that grid */ for (o_ptr = get_first_object(ty, tx); o_ptr != null; o_ptr = get_next_object(o_ptr)) { /* Check for possible combination */ if (o_ptr.similar(j_ptr, object_stack_t.OSTACK_FLOOR)) comb = true; /* Count objects */ if (!Squelch.item_ok(o_ptr)) k++; else n++; } /* Add new object */ if (!comb) k++; /* Option -- disallow stacking */ if (Option.birth_no_stacking.value && (k > 1)) continue; /* Paranoia? */ if ((k + n) > Misc.MAX_FLOOR_STACK && floor_get_idx_oldest_squelched(ty, tx) == 0) continue; /* Calculate score */ s = 1000 - (d + k * 5); /* Skip bad values */ if (s < bs) continue; /* New best value */ if (s > bs) bn = 0; /* Apply the randomizer to equivalent values */ if ((++bn >= 2) && (Random.randint0(bn) != 0)) continue; /* Keep score */ bs = s; /* Track it */ by = ty; bx = tx; /* Okay */ flag = true; } } /* Handle lack of space */ if (!flag && j_ptr.artifact == null) { /* Message */ Utilities.msg("The {0} disappear{1}.", o_name, Misc.PLURAL(plural)); /* Debug */ if (Misc.p_ptr.wizard) Utilities.msg("Breakage (no floor space)."); /* Failure */ return; } /* Find a grid */ for (i = 0; !flag; i++) { /* Bounce around */ if (i < 1000) { ty = Random.rand_spread(by, 1); tx = Random.rand_spread(bx, 1); } /* Random locations */ else { ty = Random.randint0(c.height); tx = Random.randint0(c.width); } /* Require floor space */ if (Cave.cave.feat[ty][tx] != Cave.FEAT_FLOOR) continue; /* Bounce to that location */ by = ty; bx = tx; /* Require floor space */ if (!Cave.cave_clean_bold(by, bx)) continue; /* Okay */ flag = true; } /* Give it to the floor */ if (floor_carry(c, by, bx, j_ptr) == 0) { /* Message */ Utilities.msg("The {0} disappear{1}.", o_name, Misc.PLURAL(plural)); /* Debug */ if (Misc.p_ptr.wizard) Utilities.msg("Breakage (too many objects)."); if (j_ptr.artifact != null) j_ptr.artifact.created = false; /* Failure */ return; } /* Sound */ //sound(MSG_DROP); //Nick: Add this later /* Message when an object falls under the player */ if (verbose && (Cave.cave.m_idx[by][bx] < 0) && !Squelch.item_ok(j_ptr)) { Utilities.msg("You feel something roll beneath your feet."); } }
/* * Take off (some of) a non-cursed equipment item * * Note that only one item at a time can be wielded per slot. * * Note that taking off an item when "full" may cause that item * to fall to the ground. * * Return the inventory slot into which the item is placed. */ public static short inven_takeoff(int item, int amt) { int slot; Object o_ptr; Object i_ptr; //object_type object_type_body; string act; //char o_name[80]; string o_name; bool track_removed_item = false; /* Get the item to take off */ o_ptr = Misc.p_ptr.inventory[item]; /* Paranoia */ if (amt <= 0) return (-1); /* Verify */ if (amt > o_ptr.number) amt = o_ptr.number; /* Get local object */ i_ptr = new Object();//&object_type_body; /* Obtain a local object */ i_ptr = o_ptr.copy(); //object_copy(i_ptr, o_ptr); /* Modify quantity */ i_ptr.number = (byte)amt; /* Describe the object */ o_name = i_ptr.object_desc(Detail.PREFIX | Detail.FULL); /* Took off weapon */ if (item == Misc.INVEN_WIELD) { act = "You were wielding"; } /* Took off bow */ else if (item == Misc.INVEN_BOW) { act = "You were holding"; } /* Took off light */ else if (item == Misc.INVEN_LIGHT) { act = "You were holding"; } /* Took off something */ else { act = "You were wearing"; } /* Update object_idx if necessary, after optimization */ if (Cave.tracked_object_is(item)) { track_removed_item = true; } /* Modify, Optimize */ inven_item_increase(item, -amt); inven_item_optimize(item); /* Carry the object */ slot = i_ptr.inven_carry(Misc.p_ptr); /* Track removed item if necessary */ if (track_removed_item) { Cave.track_object(slot); } /* Message */ Utilities.msgt(Message_Type.MSG_WIELD, "{0} {1} ({2}).", act, o_name, index_to_label(slot)); Misc.p_ptr.notice |= Misc.PN_SQUELCH; /* Return slot */ return (short)(slot); }
/* * Buy the item with the given index from the current store's inventory. */ public static void buy(Command_Code code, cmd_arg[] args) { int item = args[0].value; int amt = args[1].value; Object.Object o_ptr; //object_type object_type_body; Object.Object i_ptr = new Object.Object();//&object_type_body; //char o_name[80]; string o_name; int price, item_new; Store store = Store.current_store(); if (store == null) { Utilities.msg("You cannot purchase items when not in a store."); return; } /* Get the actual object */ o_ptr = store.stock[item]; /* Get desired object */ Object.Object.copy_amt(ref i_ptr, o_ptr, amt); /* Ensure we have room */ if (!i_ptr.inven_carry_okay()) { Utilities.msg("You cannot carry that many items."); return; } /* Describe the object (fully) */ o_name = i_ptr.object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); /* Extract the price for the entire stack */ price = Store.price_item(i_ptr, false, i_ptr.number); if (price > Misc.p_ptr.au) { Utilities.msg("You cannot afford that purchase."); return; } /* Spend the money */ Misc.p_ptr.au -= price; /* Update the display */ Store.store_flags |= Store.STORE_GOLD_CHANGE; /* ID objects on buy */ i_ptr.notice_everything(); /* Combine / Reorder the pack (later) */ Misc.p_ptr.notice |= (Misc.PN_COMBINE | Misc.PN_REORDER | Misc.PN_SORT_QUIVER | Misc.PN_SQUELCH); /* The object no longer belongs to the store */ i_ptr.ident &= ~(Object.Object.IDENT_STORE); /* Message */ if (Random.one_in_(3)) Utilities.msgt(Message_Type.MSG_STORE5, "{0}", Store.comment_accept[Random.randint0(Store.comment_accept.Length)]); Utilities.msg("You bought {0} for {1} gold.", o_name, (long)price); /* Erase the inscription */ i_ptr.note = null; /* Give it to the player */ item_new = i_ptr.inven_carry(Misc.p_ptr); /* Message */ o_name = Misc.p_ptr.inventory[item_new].object_desc(Object.Object.Detail.PREFIX | Object.Object.Detail.FULL); Utilities.msg("You have {0} ({1}).", o_name, Object.Object.index_to_label(item_new)); /* Hack - Reduce the number of charges in the original stack */ if (o_ptr.tval == TVal.TV_WAND || o_ptr.tval == TVal.TV_STAFF) { o_ptr.pval[Misc.DEFAULT_PVAL] -= i_ptr.pval[Misc.DEFAULT_PVAL]; } /* Handle stuff */ Misc.p_ptr.handle_stuff(); /* Remove the bought objects from the store */ store.item_increase(item, -amt); store.item_optimize(item); /* Store is empty */ if (store.stock_num == 0) { int i; /* Shuffle */ if (Random.one_in_(Store.SHUFFLE)) { /* Message */ Utilities.msg("The shopkeeper retires."); /* Shuffle the store */ store.store_shuffle(); Store.store_flags |= Store.STORE_FRAME_CHANGE; } /* Maintain */ else { /* Message */ Utilities.msg("The shopkeeper brings out some new stock."); } /* New inventory */ for (i = 0; i < 10; ++i) store.store_maint(); } Game_Event.signal(Game_Event.Event_Type.INVENTORY); Game_Event.signal(Game_Event.Event_Type.EQUIPMENT); }