/* * Drop all {squelch}able items. */ public static void drop() { int n; /* Scan through the slots backwards */ for (n = Misc.INVEN_PACK - 1; n >= 0; n--) { Object.Object o_ptr = Misc.p_ptr.inventory[n]; /* Skip non-objects and unsquelchable objects */ if (o_ptr.kind == null) { continue; } if (!item_ok(o_ptr)) { continue; } /* Check for !d (no drop) inscription */ if (!o_ptr.check_for_inscrip("!d") && !o_ptr.check_for_inscrip("!*")) { /* We're allowed to drop it. */ Object.Object.inven_drop(n, o_ptr.number); } } /* Combine/reorder the pack */ Misc.p_ptr.notice |= (Misc.PN_COMBINE | Misc.PN_REORDER); }
/* 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); }
/** * Check no currently worn items are stopping the action 'c' */ public static bool key_confirm_command(char c) { int i; /* Hack -- Scan equipment */ for (i = Misc.INVEN_WIELD; i < Misc.INVEN_TOTAL; i++) { string verify_inscrip = "^" + c; int n; Object.Object o_ptr = Misc.p_ptr.inventory[i]; if (o_ptr.kind == null) { continue; } /* Set up string to look for, e.g. "^d" */ //verify_inscrip[1] = c; /* Verify command */ n = (o_ptr.check_for_inscrip("^*")?1:0) + (o_ptr.check_for_inscrip(verify_inscrip)?1:0); while (n-- != 0) { if (!Utilities.get_check("Are you sure? ")) { return(false); } } } return(true); }
public static void wr_inventory() { int i; /* Write the inventory */ for (i = 0; i < Misc.ALL_INVEN_TOTAL; i++) { Object.Object o_ptr = Misc.p_ptr.inventory[i]; /* Skip non-objects */ if (o_ptr.kind == null) { continue; } /* Dump index */ wr_u16b((ushort)i); /* Dump object */ wr_item(o_ptr); } /* Add a sentinel */ wr_u16b(0xFFFF); }
/* * Init players with some belongings * * Having an item identifies it and makes the player "aware" of its purpose. */ static void player_outfit(Player.Player p) { //Object.Object object_type_body = new Object.Object(); /* Give the player starting equipment */ for (Start_Item si = Player.Player.instance.Class.start_items; si != null; si = si.next) { /* Get local object */ Object.Object i_ptr = new Object.Object(); /* Prepare the item */ i_ptr.prep(si.kind, 0, aspect.MINIMISE); i_ptr.number = (byte)Random.rand_range(si.min, si.max); i_ptr.origin = Origin.BIRTH; i_ptr.flavor_aware(); i_ptr.notice_everything(); i_ptr.inven_carry(p); si.kind.everseen = true; /* Deduct the cost of the item from starting cash */ p.au -= i_ptr.value(i_ptr.number, false); } /* Sanity check */ if (p.au < 0) { p.au = 0; } /* Now try wielding everything */ wield_all(p); }
/*** Squelch code ***/ /* * Squelch the flavor of an object */ public static void object_squelch_flavor_of(Object.Object o_ptr) { throw new NotImplementedException(); //if (object_flavor_is_aware(o_ptr)) // o_ptr.kind.squelch |= SQUELCH_IF_AWARE; //else // o_ptr.kind.squelch |= SQUELCH_IF_UNAWARE; }
/* * Determines if an object is eligible for squelching. */ public static bool item_ok(Object.Object o_ptr) { byte type; if (Misc.p_ptr.unignoring != 0) { return(false); } /* Don't squelch artifacts unless marked to be squelched */ if (o_ptr.artifact != null || o_ptr.check_for_inscrip("!k") || o_ptr.check_for_inscrip("!*")) { return(false); } /* Do squelch individual objects that marked ignore */ if (o_ptr.ignore) { return(true); } /* Auto-squelch dead chests */ if (o_ptr.tval == TVal.TV_CHEST && o_ptr.pval[Misc.DEFAULT_PVAL] == 0) { return(true); } /* Do squelching by kind */ if (o_ptr.flavor_is_aware() ? kind_is_squelched_aware(o_ptr.kind) : kind_is_squelched_unaware(o_ptr.kind)) { return(true); } type = (byte)type_of(o_ptr); if (type == (int)squelch_type_t.TYPE_MAX) { return(false); } /* Squelch items known not to be special */ if (o_ptr.is_known_not_artifact() && squelch_level[type] == (byte)quality_squelch.SQUELCH_ALL) { return(true); } /* Get result based on the feeling and the squelch_level */ if ((byte)squelch_level_of(o_ptr) <= squelch_level[type]) { return(true); } else { return(false); } }
/** * Small helper function to see if an item seems good, bad or average based on * to_h, to_d and to_a. * * The sign of the return value announces if the object is bad (negative), * good (positive) or average (zero). */ static int is_object_good(Object.Object o_ptr) { int good = 0; good += 4 * cmp_object_trait(o_ptr.to_d, o_ptr.kind.to_d); good += 2 * cmp_object_trait(o_ptr.to_h, o_ptr.kind.to_h); good += 1 * cmp_object_trait(o_ptr.to_a, o_ptr.kind.to_a); return(good); }
static string show_missile_weapon(Object.Object o_ptr) { Player.Player p_ptr = Player.Player.instance; int hit = p_ptr.state.dis_to_h; int dam = 0; if (o_ptr.attack_plusses_are_visible()) { hit += o_ptr.to_h; dam += o_ptr.to_d; } return("(" + hit + "," + dam + ")");; }
/** * Browse a given book. */ public static void book_browse(Object.Object o_ptr) { throw new NotImplementedException(); //menu_type *m; //const char *noun = (p_ptr.class.spell_book == TV_MAGIC_BOOK ? // "spell" : "prayer"); //m = spell_menu_new(o_ptr, spell_okay_to_browse); //if (m) { // spell_menu_browse(m, noun); // spell_menu_destroy(m); //} else { // msg("You cannot browse that."); //} }
/* * Find the squelch type of the object, or TYPE_MAX if none */ public static squelch_type_t type_of(Object.Object o_ptr) { /* Find the appropriate squelch group */ for (int i = 0; i < quality_mapping.Length; i++) { if ((quality_mapping[i].tval == o_ptr.tval) && (quality_mapping[i].min_sval <= o_ptr.sval) && (quality_mapping[i].max_sval >= o_ptr.sval)) { return(quality_mapping[i].squelch_type); } } return(squelch_type_t.TYPE_MAX); }
/** * Helper function used with ranged_helper by do_cmd_fire. */ public static attack_result make_ranged_shot(Object.Object o_ptr, int y, int x) { attack_result result = new attack_result(false, 0, 0, "hit"); Object.Object j_ptr = Misc.p_ptr.inventory[Misc.INVEN_BOW]; 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]; int bonus = Misc.p_ptr.state.to_h + o_ptr.to_h + j_ptr.to_h; int chance = Misc.p_ptr.state.skills[(int)Skill.TO_HIT_BOW] + bonus * Misc.BTH_PLUS_ADJ; int chance2 = chance - Cave.distance(Misc.p_ptr.py, Misc.p_ptr.px, y, x); int multiplier = Misc.p_ptr.state.ammo_mult; Slay best_s_ptr = null; /* Did we hit it (penalize distance travelled) */ if (!test_hit(chance2, r_ptr.ac, m_ptr.ml)) { return(result); } result.success = true; Slay.improve_attack_modifier(o_ptr, m_ptr, ref best_s_ptr, true, false); Slay.improve_attack_modifier(j_ptr, m_ptr, ref best_s_ptr, true, false); /* If we have a slay, modify the multiplier appropriately */ if (best_s_ptr != null) { result.hit_verb = best_s_ptr.range_verb; multiplier += best_s_ptr.mult; } /* Apply damage: multiplier, slays, criticals, bonuses */ result.dmg = Random.damroll(o_ptr.dd, o_ptr.ds); result.dmg += o_ptr.to_d + j_ptr.to_d; result.dmg *= multiplier; result.dmg = critical_shot(o_ptr.weight, o_ptr.to_h, result.dmg, ref result.msg_type); Misc.p_ptr.inventory[Misc.INVEN_BOW].notice_attack_plusses(); return(result); }
public static void wr_objects() { int i; if (Misc.p_ptr.is_dead) { return; } /* Total objects */ wr_u16b((ushort)Misc.o_max); /* Dump the objects */ for (i = 1; i < Misc.o_max; i++) { Object.Object o_ptr = Object.Object.byid((short)i); /* Dump it */ wr_item(o_ptr); } }
/* * Check to see if the player can use a rod/wand/staff/activatable object. */ static int check_devices(Object.Object o_ptr) { throw new NotImplementedException(); //int fail; //const char *action; //const char *what = null; ///* Get the right string */ //switch (o_ptr.tval) //{ // case TV_ROD: action = "zap the rod"; break; // case TV_WAND: action = "use the wand"; what = "wand"; break; // case TV_STAFF: action = "use the staff"; what = "staff"; break; // default: action = "activate it"; break; //} ///* Figure out how hard the item is to use */ //fail = get_use_device_chance(o_ptr); ///* Roll for usage */ //if (randint1(1000) < fail) //{ // flush(); // msg("You failed to %s properly.", action); // return false; //} ///* Notice empty staffs */ //if (what && o_ptr.pval[DEFAULT_PVAL] <= 0) //{ // flush(); // msg("The %s has no charges left.", what); // o_ptr.ident |= (IDENT_EMPTY); // return false; //} //return true; }
/* * Helper function: create an item with the given tval,sval pair, add it to the * store st. Return the slot in the inventory. */ int create_item(Object_Kind kind) { Object.Object obj = new Object.Object(); /* Create a new object of the chosen kind */ obj.prep(kind, 0, aspect.RANDOMISE); /* Item belongs to a store */ obj.ident |= Object.Object.IDENT_STORE; obj.origin = Origin.STORE; /* Attempt to carry the object */ return carry(obj); }
/* * Creates a random object and gives it to store 'st' */ bool create_random() { int tries, level; Object.Object i_ptr; //Object.Object object_type_body; int min_level, max_level; /* Decide min/max levels */ if (sidx == STORE.B_MARKET) { min_level = Misc.p_ptr.max_depth + 5; max_level = Misc.p_ptr.max_depth + 20; } else { min_level = 1; max_level = STORE_OBJ_LEVEL + Math.Max(Misc.p_ptr.max_depth - 20, 0); } if (min_level > 55) min_level = 55; if (max_level > 70) max_level = 70; /* Consider up to six items */ for (tries = 0; tries < 6; tries++) { Object_Kind kind; /* Work out the level for objects to be generated at */ level = Random.rand_range(min_level, max_level); /* Black Markets have a random object, of a given level */ if (sidx == STORE.B_MARKET) kind = Object.Object.get_obj_num(level, false); else kind = get_choice(); /*** Pre-generation filters ***/ /* No chests in stores XXX */ if (kind.tval == TVal.TV_CHEST) continue; /*** Generate the item ***/ /* Get local object */ i_ptr = new Object.Object(); //i_ptr = object_type_body; /* Create a new object of the chosen kind */ i_ptr.prep(kind, level, aspect.RANDOMISE); /* Apply some "low-level" magic (no artifacts) */ i_ptr.apply_magic(level, false, false, false); /* Reject if item is 'damaged' (i.e. negative mods) */ switch (i_ptr.tval) { case TVal.TV_DIGGING: case TVal.TV_HAFTED: case TVal.TV_POLEARM: case TVal.TV_SWORD: case TVal.TV_BOW: case TVal.TV_SHOT: case TVal.TV_ARROW: case TVal.TV_BOLT: { if ((i_ptr.to_h < 0) || (i_ptr.to_d < 0)) continue; if (i_ptr.to_a < 0) continue; break; } case TVal.TV_DRAG_ARMOR: case TVal.TV_HARD_ARMOR: case TVal.TV_SOFT_ARMOR: case TVal.TV_SHIELD: case TVal.TV_HELM: case TVal.TV_CROWN: case TVal.TV_CLOAK: case TVal.TV_GLOVES: case TVal.TV_BOOTS: { if (i_ptr.to_a < 0) continue; break; } } /* The object is "known" and belongs to a store */ i_ptr.ident |= Object.Object.IDENT_STORE; i_ptr.origin = Origin.STORE; /*** Post-generation filters ***/ /* Black markets have expensive tastes */ if ((sidx == STORE.B_MARKET) && !black_market_ok(i_ptr)) continue; /* No "worthless" items */ if (i_ptr.value(1, false) < 1) continue; /* Mass produce and/or apply discount */ mass_produce(i_ptr); /* Attempt to carry the object */ carry(i_ptr); /* Definitely done */ return true; } return false; }
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(); } }
/* * 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; }
/* * Init players with some belongings * * Having an item identifies it and makes the player "aware" of its purpose. */ static void player_outfit(Player.Player p) { //Object.Object object_type_body = new Object.Object(); /* Give the player starting equipment */ for (Start_Item si = Player.Player.instance.Class.start_items; si != null; si = si.next) { /* Get local object */ Object.Object i_ptr = new Object.Object(); /* Prepare the item */ i_ptr.prep(si.kind, 0, aspect.MINIMISE); i_ptr.number = (byte)Random.rand_range(si.min, si.max); i_ptr.origin = Origin.BIRTH; i_ptr.flavor_aware(); i_ptr.notice_everything(); i_ptr.inven_carry(p); si.kind.everseen = true; /* Deduct the cost of the item from starting cash */ p.au -= i_ptr.value(i_ptr.number, false); } /* Sanity check */ if (p.au < 0) p.au = 0; /* Now try wielding everything */ wield_all(p); }
/** * Try to wield everything wieldable in the inventory. */ static void wield_all(Player.Player p) { Object.Object o_ptr; Object.Object i_ptr; //Object.Object object_type_body; int slot; int item; int num; bool is_ammo; /* Scan through the slots backwards */ for (item = Misc.INVEN_PACK - 1; item >= 0; item--) { o_ptr = p.inventory[item]; is_ammo = o_ptr.is_ammo(); /* Skip non-objects */ if (o_ptr.kind == null) continue; /* Make sure we can wield it */ slot = o_ptr.wield_slot(); if (slot < Misc.INVEN_WIELD) continue; i_ptr = p.inventory[slot]; if (i_ptr.kind != null && (!is_ammo ||(is_ammo && !o_ptr.similar(i_ptr, Object.Object.object_stack_t.OSTACK_PACK)))) continue; /* Figure out how much of the item we'll be wielding */ num = is_ammo ? o_ptr.number : 1; /* Get local object */ i_ptr = new Object.Object(); i_ptr = o_ptr.copy(); //This entire bit was uber shadey... Rewrote above ////i_ptr = object_type_body; //p.inventory[slot] = o_ptr; //object_copy(i_ptr, o_ptr); //This might not work... //i_ptr = o_ptr; //If wonky equips happen, check here /* Modify quantity */ i_ptr.number = (byte)num; /* Decrease the item (from the pack) */ Object.Object.inven_item_increase(item, -num); Object.Object.inven_item_optimize(item); /* Get the wield slot */ //o_ptr = p.inventory[slot]; /* Wear the new stuff */ //object_copy(o_ptr, i_ptr); p.inventory[slot] = i_ptr; /* Increase the weight */ p.total_weight += i_ptr.weight * i_ptr.number; /* Increment the equip counter by hand */ p.equip_cnt++; } Object.Object.save_quiver_size(p); return; }
///** // * Place random stairs at (x, y). // */ //static void place_random_stairs(Cave c, int y, int x) { // int feat = randint0(100) < 50 ? FEAT_LESS : FEAT_MORE; // if (cave_canputitem(c, y, x)) // place_stairs(c, y, x, feat); //} /** * Place a random object at (x, y). */ public static void place_object(Cave c, int y, int x, int level, bool good, bool great, Origin origin) { int rating = 0; Object.Object otype; Misc.assert(cave_in_bounds(c, y, x)); if (!cave_canputitem(c, y, x)) return; otype = new Object.Object(); //object_wipe(&otype); if (!Object.Object.make_object(c, ref otype, level, good, great, ref rating)) return; otype.origin = origin; otype.origin_depth = (byte)c.depth; /* Give it to the floor */ /* XXX Should this be done in floor_carry? */ if (Object.Object.floor_carry(c, y, x, otype) == 0) { if (otype.artifact != null) otype.artifact.created = false; return; } else { if (otype.artifact != null) c.good_item = true; c.obj_rating += (uint)rating; } }
/** * 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); } }
static void display_resistance_panel(player_flag_record[] resists, int size, Region bounds) { Player.Player p_ptr = Player.Player.instance; int col = bounds.col; int row = bounds.row; Term.putstr(col, row++, RES_COLS, ConsoleColor.White, " abcdefghijkl@"); for (int i = 0; i < size - 3; i++, row++) { ConsoleColor name_attr = ConsoleColor.White; Term.gotoxy(col + 6, row); /* repeated extraction of flags is inefficient but more natural */ for (int j = Misc.INVEN_WIELD; j <= Misc.INVEN_TOTAL; j++) { Object.Object o_ptr = p_ptr.inventory[j]; Bitflag f = new Bitflag(Object_Flag.SIZE); ConsoleColor[] alternatingcols = new ConsoleColor[] { ConsoleColor.Gray, ConsoleColor.DarkGray }; ConsoleColor attr = alternatingcols[j % 2]; /* alternating columns */ char sym = '.'; bool res, imm, vuln; /* Wipe flagset */ f.wipe(); if (j < Misc.INVEN_TOTAL && o_ptr.kind != null) { o_ptr.object_flags_known(ref f); } else if (j == Misc.INVEN_TOTAL) { Player.Player.player_flags(ref f); /* If the race has innate infravision/digging, force the corresponding flag * here. If we set it in player_flags(), then all callers of that * function will think the infravision is caused by equipment. */ if (p_ptr.Race.infra > 0) { f.on(Object_Flag.INFRA.value); } if (p_ptr.Race.r_skills[(int)Skill.DIGGING] > 0) { f.on(Object_Flag.TUNNEL.value); } } res = f.has(resists[i].res_flag.value); imm = f.has(resists[i].im_flag.value); vuln = f.has(resists[i].vuln_flag.value); if (imm) { name_attr = ConsoleColor.DarkGreen; } else if (res && name_attr == ConsoleColor.White) { name_attr = ConsoleColor.Cyan; } if (vuln) { sym = '-'; } else if (imm) { sym = '*'; } else if (res) { sym = '+'; } else if ((j < Misc.INVEN_TOTAL) && o_ptr.kind != null && !o_ptr.object_flag_is_known(resists[i].res_flag.value)) { sym = '?'; } Term.addch(attr, sym); } Term.putstr(col, row, 6, name_attr, resists[i].name.ToString()); } Term.putstr(col, row++, RES_COLS, ConsoleColor.White, " abcdefghijkl@"); /* Equippy */ display_player_equippy(row++, col + 6); }
/* * Request a game command from the uI and carry out whatever actions * go along with it. */ public static void process_command(cmd_context ctx, bool no_request) { Game_Command cmd = new Game_Command(); /* Reset so that when selecting items, we look in the default location */ Misc.p_ptr.command_wrk = 0; /* If we've got a command to process, do it. */ if (get(ctx, ref cmd, !no_request) != null) //Was ==null... { int oldrepeats = cmd.nrepeats; int idx = cmd_idx(cmd.command); int i; if (idx == -1) { return; } for (i = 0; i < item_selector.Length; i++) { item_selector_type itms = item_selector[i]; if (itms.command != cmd.command) { continue; } if (!cmd.arg_present[0]) { int item = 0; Misc.item_tester_hook = itms.filter; if (!Object.Object.get_item(ref item, itms.prompt, itms.noop, cmd.command, itms.mode)) { return; } cmd.set_arg_item(0, item); } } /* XXX avoid dead objects from being re-used on repeat. * this needs to be expanded into a general safety-check * on args */ if ((game_cmds[idx].arg_type[0] == cmd_arg_type.arg_ITEM) && cmd.arg_present[0]) { Object.Object o_ptr = Object.Object.object_from_item_idx(cmd.arg[0].value); if (o_ptr.kind == null) { return; } } /* Do some sanity checking on those arguments that might have * been declared as "unknown", such as directions and targets. */ switch (cmd.command) { case Command_Code.INSCRIBE: { throw new NotImplementedException(); //char o_name[80]; //char tmp[80] = ""; //object_type *o_ptr = object_from_item_idx(cmd.arg[0].item); //object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); //msg("Inscribing %s.", o_name); //message_flush(); ///* Use old inscription */ //if (o_ptr.note) // strnfmt(tmp, sizeof(tmp), "%s", quark_str(o_ptr.note)); ///* Get a new inscription (possibly empty) */ //if (!get_string("Inscription: ", tmp, sizeof(tmp))) // return; //cmd_set_arg_string(cmd, 1, tmp); //break; } case Command_Code.OPEN: { throw new NotImplementedException(); //if (Option.easy_open.value && (!cmd.arg_present[0] || // cmd.arg[0].value == (int)Direction.UNKNOWN)) //{ // int y, x; // int n_closed_doors, n_locked_chests; // throw new NotImplementedException(); // n_closed_doors = count_feats(&y, &x, cave_iscloseddoor, false); // n_locked_chests = count_chests(&y, &x, false); // if (n_closed_doors + n_locked_chests == 1) // cmd_set_arg_direction(cmd, 0, coords_to_dir(y, x)); //} //goto get_dir; } case Command_Code.CLOSE: { throw new NotImplementedException(); //if (OPT(easy_open) && (!cmd.arg_present[0] || // cmd.arg[0].direction == DIR_UNKNOWN)) //{ // int y, x; // /* Count open doors */ // if (count_feats(&y, &x, cave_isopendoor, false) == 1) // cmd_set_arg_direction(cmd, 0, coords_to_dir(y, x)); //} //goto get_dir; } case Command_Code.DISARM: { throw new NotImplementedException(); //if (OPT(easy_open) && (!cmd.arg_present[0] || // cmd.arg[0].direction == DIR_UNKNOWN)) //{ // int y, x; // int n_visible_traps, n_trapped_chests; // n_visible_traps = count_feats(&y, &x, cave_isknowntrap, true); // n_trapped_chests = count_chests(&y, &x, true); // if (n_visible_traps + n_trapped_chests == 1) // cmd_set_arg_direction(cmd, 0, coords_to_dir(y, x)); //} //goto get_dir; } case Command_Code.TUNNEL: case Command_Code.WALK: case Command_Code.RUN: case Command_Code.JUMP: case Command_Code.BASH: case Command_Code.ALTER: case Command_Code.JAM: { get_dir: /* Direction hasn't been specified, so we ask for one. */ if (!cmd.arg_present[0] || cmd.arg[0].value == (int)Direction.UNKNOWN) { int dir; if (!Xtra2.get_rep_dir(out dir)) { return; } cmd.set_arg_direction(0, dir); } break; } case Command_Code.DROP: { throw new NotImplementedException(); //if (!cmd.arg_present[1]) //{ // object_type *o_ptr = object_from_item_idx(cmd.arg[0].item); // int amt = get_quantity(null, o_ptr.number); // if (amt <= 0) // return; // cmd_set_arg_number(cmd, 1, amt); //} //break; } /* * These take an item number and a "target" as arguments, * though a target isn't always actually needed, so we'll * only prompt for it via callback if the item being used needs it. */ case Command_Code.USE_WAND: case Command_Code.USE_ROD: case Command_Code.QUAFF: case Command_Code.ACTIVATE: case Command_Code.READ_SCROLL: case Command_Code.FIRE: case Command_Code.THROW: { bool get_target = false; Object.Object o_ptr = Object.Object.object_from_item_idx(cmd.arg[0].value); /* If we couldn't resolve the item, then abort this */ if (o_ptr.kind == null) { break; } /* Thrown objects always need an aim, others might, depending * on the object */ if (o_ptr.needs_aim() || cmd.command == Command_Code.THROW) { if (!cmd.arg_present[1]) { get_target = true; } else if (cmd.arg[1].value == (int)Direction.UNKNOWN) { get_target = true; } else if (cmd.arg[1].value == (int)Direction.TARGET && !Target.okay()) { get_target = true; } } cmd.arg[1] = new cmd_arg(); cmd.arg[1].value = 0; if (get_target && !Xtra2.get_aim_dir(ref cmd.arg[1].value)) { return; } Misc.p_ptr.confuse_dir(ref cmd.arg[1].value, false); cmd.arg_present[1] = true; break; } /* This takes a choice and a direction. */ case Command_Code.CAST: { throw new NotImplementedException(); //bool get_target = false; //if (spell_needs_aim(Misc.p_ptr.Class.spell_book, cmd.arg[0].choice)) //{ // if (!cmd.arg_present[1]) // get_target = true; // if (cmd.arg[1].direction == DIR_UNKNOWN) // get_target = true; // if (cmd.arg[1].direction == DIR_TARGET && !target_okay()) // get_target = true; //} //if (get_target && !get_aim_dir(&cmd.arg[1].direction)) // return; //player_confuse_dir(p_ptr, &cmd.arg[1].direction, false); //cmd.arg_present[1] = true; //break; } case Command_Code.WIELD: { Object.Object o_ptr = Object.Object.object_from_item_idx(cmd.arg[0].value); int slot = o_ptr.wield_slot(); /* Usually if the slot is taken we'll just replace the item in the slot, * but in some cases we need to ask the user which slot they actually * want to replace */ if (Misc.p_ptr.inventory[slot].kind != null) { if (o_ptr.tval == Object.TVal.TV_RING) { string q = "Replace which ring? "; string s = "Error in obj_wield, please report"; Misc.item_tester_hook = Object.Object.obj_is_ring; if (!Object.Object.get_item(ref slot, q, s, Command_Code.WIELD, Misc.USE_EQUIP)) { return; } } if (o_ptr.is_ammo() && !Misc.p_ptr.inventory[slot].similar(o_ptr, Object.Object.object_stack_t.OSTACK_QUIVER)) { string q = "Replace which ammunition? "; string s = "Error in obj_wield, please report"; Misc.item_tester_hook = Object.Object.obj_is_ammo; if (!Object.Object.get_item(ref slot, q, s, Command_Code.WIELD, Misc.USE_EQUIP)) { return; } } } /* Set relevant slot */ cmd.set_arg_number(1, slot); break; } default: { /* I can see the point of the compiler warning, but still... */ break; } } /* Command repetition */ if (game_cmds[idx].repeat_allowed) { /* Auto-repeat only if there isn't already a repeat length. */ if (game_cmds[idx].nrepeats > 0 && cmd.nrepeats == 0) { Game_Command.set_repeat(game_cmds[idx].nrepeats); } } else { cmd.nrepeats = 0; repeating = false; } /* * The command gets to unset this if it isn't appropriate for * the user to repeat it. */ repeat_prev_allowed = true; if (game_cmds[idx].fn != null) { game_cmds[idx].fn(cmd.command, cmd.arg); } /* If the command hasn't changed nrepeats, count this execution. */ if (cmd.nrepeats > 0 && oldrepeats == Game_Command.get_nrepeats()) { Game_Command.set_repeat(oldrepeats - 1); } } }
/* * Special display, part 2c * * How to print out the modifications and sustains. * Positive mods with no sustain will be light green. * Positive mods with a sustain will be dark green. * Sustains (with no modification) will be a dark green 's'. * Negative mods (from a curse) will be red. * Huge mods (>9), like from MICoMorgoth, will be a '*' * No mod, no sustain, will be a slate '.' */ static void display_player_sust_info() { int j, stat; Player.Player p_ptr = Player.Player.instance; Bitflag f = new Bitflag(Object_Flag.SIZE); Object_Flag[] stat_flags = new Object_Flag[(int)Stat.Max]; Object_Flag[] sustain_flags = new Object_Flag[(int)Stat.Max]; ConsoleColor a; char c; /* Row */ int row = 2; /* Column */ int col = 26; /* Build the stat flags tables */ stat_flags[(int)Stat.Str] = Object_Flag.STR; stat_flags[(int)Stat.Int] = Object_Flag.INT; stat_flags[(int)Stat.Wis] = Object_Flag.WIS; stat_flags[(int)Stat.Dex] = Object_Flag.DEX; stat_flags[(int)Stat.Con] = Object_Flag.CON; stat_flags[(int)Stat.Chr] = Object_Flag.CHR; sustain_flags[(int)Stat.Str] = Object_Flag.SUST_STR; sustain_flags[(int)Stat.Int] = Object_Flag.SUST_INT; sustain_flags[(int)Stat.Wis] = Object_Flag.SUST_WIS; sustain_flags[(int)Stat.Dex] = Object_Flag.SUST_DEX; sustain_flags[(int)Stat.Con] = Object_Flag.SUST_CON; sustain_flags[(int)Stat.Chr] = Object_Flag.SUST_CHR; /* Header */ Utilities.c_put_str(ConsoleColor.White, "abcdefghijkl@", row - 1, col); /* Process equipment */ for (int i = Misc.INVEN_WIELD; i < Misc.INVEN_TOTAL; ++i) { /* Get the object */ Object.Object o_ptr = p_ptr.inventory[i]; if (o_ptr.kind == null) { col++; continue; } /* Get the "known" flags */ o_ptr.object_flags_known(ref f); /* Initialize color based of sign of pval. */ for (stat = 0; stat < (int)Stat.Max; stat++) { /* Default */ a = ConsoleColor.Gray; c = '.'; /* Boost */ if (f.has(stat_flags[stat].value)) { /* Default */ c = '*'; /* Work out which pval we're talking about */ j = o_ptr.which_pval(stat_flags[stat].value); /* Good */ if (o_ptr.pval[j] > 0) { /* Good */ a = ConsoleColor.Green; /* Label boost */ if (o_ptr.pval[j] < 10) { c = (char)Basic.I2D((char)o_ptr.pval[j]); } } /* Bad */ if (o_ptr.pval[j] < 0) { /* Bad */ a = ConsoleColor.Red; /* Label boost */ if (o_ptr.pval[j] > -10) { c = (char)Basic.I2D((char)-(o_ptr.pval[j])); } } } /* Sustain */ if (f.has(sustain_flags[stat].value)) { /* Dark green */ a = ConsoleColor.DarkGreen; /* Convert '.' to 's' */ if (c == '.') { c = 's'; } } if ((c == '.') && o_ptr.kind != null && !o_ptr.object_flag_is_known(sustain_flags[stat].value)) { c = '?'; } /* Dump proper character */ Term.putch(col, row + stat, a, c); } /* Advance */ col++; } /* Player flags */ Player.Player.player_flags(ref f); /* Check stats */ for (stat = 0; stat < (int)Stat.Max; ++stat) { /* Default */ a = ConsoleColor.Gray; c = '.'; /* Sustain */ if (f.has(sustain_flags[stat].value)) { /* Dark green "s" */ a = ConsoleColor.DarkGreen; c = 's'; } /* Dump */ Term.putch(col, row + stat, a, c); } /* Column */ col = 26; /* Footer */ Utilities.c_put_str(ConsoleColor.White, "abcdefghijkl@", row + 6, col); /* Equippy */ display_player_equippy(row + 7, col); }
/* * Write an "item" record */ static void wr_item(Object.Object o_ptr) { int i, j; wr_u16b(0xffff); wr_byte(Savefile.ITEM_VERSION); wr_s16b(0); /* Location */ wr_byte(o_ptr.iy); wr_byte(o_ptr.ix); wr_byte(o_ptr.tval); wr_byte(o_ptr.sval); for (i = 0; i < Misc.MAX_PVALS; i++) { wr_s16b(o_ptr.pval[i]); } wr_byte(o_ptr.num_pvals); wr_byte(0); wr_byte(o_ptr.number); wr_s16b(o_ptr.weight); if (o_ptr.artifact != null) { wr_byte((byte)o_ptr.artifact.aidx); } else { wr_byte(0); } if (o_ptr.ego != null) { wr_byte((byte)o_ptr.ego.eidx); } else { wr_byte(0); } wr_s16b(o_ptr.timeout); wr_s16b(o_ptr.to_h); wr_s16b(o_ptr.to_d); wr_s16b(o_ptr.to_a); wr_s16b(o_ptr.ac); wr_byte(o_ptr.dd); wr_byte(o_ptr.ds); wr_u16b((ushort)o_ptr.ident); wr_byte(o_ptr.marked); wr_byte((byte)o_ptr.origin); wr_byte(o_ptr.origin_depth); wr_u16b((ushort)o_ptr.origin_xtra); for (i = 0; i < Object.Object_Flag.BYTES && i < Object.Object_Flag.SIZE; i++) { wr_byte(o_ptr.flags[i]); } if (i < Object.Object_Flag.BYTES) { Savefile.pad_bytes(Object.Object_Flag.BYTES - i); } for (i = 0; i < Object.Object_Flag.BYTES && i < Object.Object_Flag.SIZE; i++) { wr_byte(o_ptr.known_flags[i]); } if (i < Object.Object_Flag.BYTES) { Savefile.pad_bytes(Object.Object_Flag.BYTES - i); } for (j = 0; j < Misc.MAX_PVALS; j++) { for (i = 0; i < Object.Object_Flag.BYTES && i < Object.Object_Flag.SIZE; i++) { wr_byte(o_ptr.pval_flags[j][i]); } if (i < Object.Object_Flag.BYTES) { Savefile.pad_bytes(Object.Object_Flag.BYTES - i); } } /* Held by monster index */ wr_s16b(o_ptr.held_m_idx); wr_s16b(o_ptr.mimicking_m_idx); /* Save the inscription (if any) */ if (o_ptr.note != null) { wr_string(o_ptr.note.ToString()); } else { wr_string(""); } }
/** * 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); } }
/* * Remove a slot if it is empty, in store 'st'. */ public void item_optimize(int item) { int j; Object.Object o_ptr; /* Get the object */ o_ptr = stock[item]; /* Must exist */ if (o_ptr.kind == null) return; /* Must have no items */ if (o_ptr.number != 0) return; /* One less object */ stock_num--; /* Slide everyone */ for (j = item; j < stock_num; j++) { stock[j] = stock[j + 1]; } /* Nuke the final slot */ stock[j] = new Object.Object(); //object_wipe(&store.stock[j]); }
/* * 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); } }
/** * Place a random amount of gold at (x, y). */ public static void place_gold(Cave c, int y, int x, int level, Origin origin) { Object.Object i_ptr; //object_type object_type_body; Misc.assert(cave_in_bounds(c, y, x)); if (!cave_canputitem(c, y, x)) return; //i_ptr = &object_type_body; //object_wipe(i_ptr); i_ptr = new Object.Object(); Object.Object.make_gold(ref i_ptr, level, (int)SVal.sval_gold.SV_GOLD_ANY); i_ptr.origin = origin; i_ptr.origin_depth = (byte)level; Object.Object.floor_carry(c, y, x, i_ptr); }
/* * 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); }
/* * Determine the squelch level of an object, which is similar to its pseudo. * * The main point is when the value is undetermined given current info, * return the maximum possible value. */ public static quality_squelch squelch_level_of(Object.Object o_ptr) { quality_squelch value = quality_squelch.SQUELCH_NONE; Bitflag f = new Bitflag(Object_Flag.SIZE); Bitflag f2 = new Bitflag(Object_Flag.SIZE); int i; o_ptr.object_flags_known(ref f); /* Deal with jewelry specially. */ if (o_ptr.is_jewelry()) { /* CC: average jewelry has at least one known positive pval */ for (i = 0; i < o_ptr.num_pvals; i++) { if ((o_ptr.this_pval_is_visible(i)) && (o_ptr.pval[i] > 0)) { return(quality_squelch.SQUELCH_AVERAGE); } } if ((o_ptr.to_h > 0) || (o_ptr.to_d > 0) || (o_ptr.to_a > 0)) { return(quality_squelch.SQUELCH_AVERAGE); } if ((o_ptr.attack_plusses_are_visible() && ((o_ptr.to_h < 0) || (o_ptr.to_d < 0))) || (o_ptr.defence_plusses_are_visible() && o_ptr.to_a < 0)) { return(quality_squelch.SQUELCH_BAD); } return(quality_squelch.SQUELCH_AVERAGE); } /* And lights */ if (o_ptr.tval == TVal.TV_LIGHT) { Object_Flag.create_mask(f2, true, Object_Flag.object_flag_id.WIELD); if (f.is_inter(f2)) { return(quality_squelch.SQUELCH_ALL); } if ((o_ptr.to_h > 0) || (o_ptr.to_d > 0) || (o_ptr.to_a > 0)) { return(quality_squelch.SQUELCH_GOOD); } if ((o_ptr.to_h < 0) || (o_ptr.to_d < 0) || (o_ptr.to_a < 0)) { return(quality_squelch.SQUELCH_BAD); } return(quality_squelch.SQUELCH_AVERAGE); } /* CC: we need to redefine "bad" with multiple pvals * At the moment we use "all pvals known and negative" */ for (i = 0; i < o_ptr.num_pvals; i++) { if (!o_ptr.this_pval_is_visible(i) || (o_ptr.pval[i] > 0)) { break; } if (i == (o_ptr.num_pvals - 1)) { return(quality_squelch.SQUELCH_BAD); } } if (o_ptr.was_sensed()) { Object.Object.obj_pseudo_t pseudo = o_ptr.pseudo(); switch (pseudo) { case Object.Object.obj_pseudo_t.INSCRIP_AVERAGE: { value = quality_squelch.SQUELCH_AVERAGE; break; } case Object.Object.obj_pseudo_t.INSCRIP_EXCELLENT: { /* have to assume splendid until you have tested it */ if (o_ptr.was_worn()) { if (o_ptr.high_resist_is_possible()) { value = quality_squelch.SQUELCH_EXCELLENT_NO_SPL; } else { value = quality_squelch.SQUELCH_EXCELLENT_NO_HI; } } else { value = quality_squelch.SQUELCH_ALL; } break; } case Object.Object.obj_pseudo_t.INSCRIP_SPLENDID: value = quality_squelch.SQUELCH_ALL; break; case Object.Object.obj_pseudo_t.INSCRIP_null: case Object.Object.obj_pseudo_t.INSCRIP_SPECIAL: value = quality_squelch.SQUELCH_MAX; break; /* This is the interesting case */ case Object.Object.obj_pseudo_t.INSCRIP_STRANGE: case Object.Object.obj_pseudo_t.INSCRIP_MAGICAL: { value = quality_squelch.SQUELCH_GOOD; if ((o_ptr.attack_plusses_are_visible() || Random.randcalc_valid(o_ptr.kind.to_h, o_ptr.to_h) || Random.randcalc_valid(o_ptr.kind.to_d, o_ptr.to_d)) && (o_ptr.defence_plusses_are_visible() || Random.randcalc_valid(o_ptr.kind.to_a, o_ptr.to_a))) { int isgood = is_object_good(o_ptr); if (isgood > 0) { value = quality_squelch.SQUELCH_GOOD; } else if (isgood < 0) { value = quality_squelch.SQUELCH_BAD; } else { value = quality_squelch.SQUELCH_AVERAGE; } } break; } default: /* do not handle any other possible pseudo values */ Misc.assert(false); break; } } else { if (o_ptr.was_worn()) { value = quality_squelch.SQUELCH_EXCELLENT_NO_SPL; /* object would be sensed if it were splendid */ } else if (o_ptr.is_known_not_artifact()) { value = quality_squelch.SQUELCH_ALL; } else { value = quality_squelch.SQUELCH_MAX; } } return(value); }
/** * Try to wield everything wieldable in the inventory. */ static void wield_all(Player.Player p) { Object.Object o_ptr; Object.Object i_ptr; //Object.Object object_type_body; int slot; int item; int num; bool is_ammo; /* Scan through the slots backwards */ for (item = Misc.INVEN_PACK - 1; item >= 0; item--) { o_ptr = p.inventory[item]; is_ammo = o_ptr.is_ammo(); /* Skip non-objects */ if (o_ptr.kind == null) { continue; } /* Make sure we can wield it */ slot = o_ptr.wield_slot(); if (slot < Misc.INVEN_WIELD) { continue; } i_ptr = p.inventory[slot]; if (i_ptr.kind != null && (!is_ammo || (is_ammo && !o_ptr.similar(i_ptr, Object.Object.object_stack_t.OSTACK_PACK)))) { continue; } /* Figure out how much of the item we'll be wielding */ num = is_ammo ? o_ptr.number : 1; /* Get local object */ i_ptr = new Object.Object(); i_ptr = o_ptr.copy(); //This entire bit was uber shadey... Rewrote above ////i_ptr = object_type_body; //p.inventory[slot] = o_ptr; //object_copy(i_ptr, o_ptr); //This might not work... //i_ptr = o_ptr; //If wonky equips happen, check here /* Modify quantity */ i_ptr.number = (byte)num; /* Decrease the item (from the pack) */ Object.Object.inven_item_increase(item, -num); Object.Object.inven_item_optimize(item); /* Get the wield slot */ //o_ptr = p.inventory[slot]; /* Wear the new stuff */ //object_copy(o_ptr, i_ptr); p.inventory[slot] = i_ptr; /* Increase the weight */ p.total_weight += i_ptr.weight * i_ptr.number; /* Increment the equip counter by hand */ p.equip_cnt++; } Object.Object.save_quiver_size(p); return; }
/** * Attack the monster at the given location with a single blow. */ static bool py_attack_real(int y, int x, ref bool fear) { /* Information about the target of the attack */ 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]; //char m_name[80]; string m_name; bool stop = false; /* The weapon used */ Object.Object o_ptr = Misc.p_ptr.inventory[Misc.INVEN_WIELD]; /* Information about the attack */ int bonus = Misc.p_ptr.state.to_h + o_ptr.to_h; int chance = Misc.p_ptr.state.skills[(int)Skill.TO_HIT_MELEE] + bonus * Misc.BTH_PLUS_ADJ; bool do_quake = false; bool success = false; /* Default to punching for one damage */ string hit_verb = "punch"; int dmg = 1; Message_Type msg_type = Message_Type.MSG_HIT; /* Extract monster name (or "it") */ m_name = m_ptr.monster_desc(0); /* Auto-Recall if possible and visible */ if (m_ptr.ml) { Cave.monster_race_track(m_ptr.r_idx); } /* Track a new monster */ if (m_ptr.ml) { Cave.health_track(Misc.p_ptr, Cave.cave.m_idx[y][x]); } /* Handle player fear (only for invisible monsters) */ if (Misc.p_ptr.check_state(Object_Flag.AFRAID, Misc.p_ptr.state.flags)) { Utilities.msgt(Message_Type.MSG_AFRAID, "You are too afraid to attack {0}!", m_name); return(false); } /* Disturb the monster */ Monster.Monster.mon_clear_timed(Cave.cave.m_idx[y][x], (int)Misc.MON_TMD.SLEEP, Misc.MON_TMD_FLG_NOMESSAGE, false); /* See if the player hit */ success = test_hit(chance, (int)r_ptr.ac, m_ptr.ml); /* If a miss, skip this hit */ if (!success) { Utilities.msgt(Message_Type.MSG_MISS, "You miss {0}.", m_name); return(false); } /* Handle normal weapon */ if (o_ptr.kind != null) { int i; Slay best_s_ptr = null; hit_verb = "hit"; /* Get the best attack from all slays or * brands on all non-launcher equipment */ for (i = Misc.INVEN_LEFT; i < Misc.INVEN_TOTAL; i++) { Object.Object obj = Misc.p_ptr.inventory[i]; if (obj.kind != null) { Slay.improve_attack_modifier(obj, m_ptr, ref best_s_ptr, true, false); } } Slay.improve_attack_modifier(o_ptr, m_ptr, ref best_s_ptr, true, false); if (best_s_ptr != null) { hit_verb = best_s_ptr.melee_verb; } dmg = Random.damroll(o_ptr.dd, o_ptr.ds); dmg *= (best_s_ptr == null) ? 1 : best_s_ptr.mult; dmg += o_ptr.to_d; dmg = critical_norm(o_ptr.weight, o_ptr.to_h, dmg, ref msg_type); /* Learn by use for the weapon */ o_ptr.notice_attack_plusses(); if (Misc.p_ptr.check_state(Object_Flag.IMPACT, Misc.p_ptr.state.flags) && dmg > 50) { do_quake = true; Object.Object.wieldeds_notice_flag(Misc.p_ptr, Object_Flag.IMPACT.value); } } /* Learn by use for other equipped items */ Object.Object.wieldeds_notice_on_attack(); /* Apply the player damage bonuses */ dmg += Misc.p_ptr.state.to_d; /* No negative damage */ if (dmg <= 0) { dmg = 0; } /* Tell the player what happened */ if (dmg <= 0) { Utilities.msgt(Message_Type.MSG_MISS, "You fail to harm {0}.", m_name); } else if (msg_type == Message_Type.MSG_HIT) { Utilities.msgt(Message_Type.MSG_HIT, "You {0} {1}.", hit_verb, m_name); } else if (msg_type == Message_Type.MSG_HIT_GOOD) { Utilities.msgt(Message_Type.MSG_HIT_GOOD, "You {0} {1}. {2}", hit_verb, m_name, "It was a good hit!"); } else if (msg_type == Message_Type.MSG_HIT_GREAT) { Utilities.msgt(Message_Type.MSG_HIT_GREAT, "You {0} {1}. {2}", hit_verb, m_name, "It was a great hit!"); } else if (msg_type == Message_Type.MSG_HIT_SUPERB) { Utilities.msgt(Message_Type.MSG_HIT_SUPERB, "You {0} {1}. {2}", hit_verb, m_name, "It was a superb hit!"); } else if (msg_type == Message_Type.MSG_HIT_HI_GREAT) { Utilities.msgt(Message_Type.MSG_HIT_HI_GREAT, "You {0} {1}. {2}", hit_verb, m_name, "It was a *GREAT* hit!"); } else if (msg_type == Message_Type.MSG_HIT_HI_SUPERB) { Utilities.msgt(Message_Type.MSG_HIT_HI_SUPERB, "You {0} {1}. {2}", hit_verb, m_name, "It was a *SUPERB* hit!"); } /* Complex message */ if (Misc.p_ptr.wizard) { Utilities.msg("You do {0} (out of {1}) damage.", dmg, m_ptr.hp); } /* Confusion attack */ if (Misc.p_ptr.confusing != 0) { Misc.p_ptr.confusing = 0; //false; Utilities.msg("Your hands stop glowing."); Monster.Monster.mon_inc_timed(Cave.cave.m_idx[y][x], Misc.MON_TMD.CONF, (10 + Random.randint0(Misc.p_ptr.lev) / 10), Misc.MON_TMD_FLG_NOTIFY, false); } /* Damage, check for fear and death */ stop = Monster.Monster_Make.mon_take_hit(Cave.cave.m_idx[y][x], dmg, ref fear, null); if (stop) { fear = false; } /* Apply earthquake brand */ if (do_quake) { throw new NotImplementedException(); //earthquake(Misc.p_ptr.py, Misc.p_ptr.px, 10); //if (Cave.cave.m_idx[y][x] == 0) stop = true; } return(stop); }
/* * 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); }