static int obj_desc_inscrip(Object o_ptr, ref string buf, int max, int end) { string[] u = { "", "", "", "" }; int n = 0; Object.obj_pseudo_t feel = o_ptr.pseudo(); Bitflag flags_known = new Bitflag(Object_Flag.SIZE); Bitflag f2 = new Bitflag(Object_Flag.SIZE); o_ptr.object_flags_known(ref flags_known); /* Get inscription */ if (o_ptr.note != null && o_ptr.note.value != null) { u[n++] = o_ptr.note.ToString(); } /* Use special inscription, if any */ if (!o_ptr.is_known() && feel != 0) { /* cannot tell excellent vs strange vs splendid until wield */ if (!o_ptr.was_worn() && o_ptr.ego != null) { u[n++] = "ego"; } else { u[n++] = Misc.inscrip_text[(int)feel]; //I know that feel bro. } } else if (((o_ptr.ident & Object.IDENT_EMPTY) != 0) && !o_ptr.is_known()) { u[n++] = "empty"; } else if (!o_ptr.is_known() && o_ptr.was_worn()) { if (o_ptr.wield_slot() == Misc.INVEN_WIELD || o_ptr.wield_slot() == Misc.INVEN_BOW) { u[n++] = "wielded"; } else { u[n++] = "worn"; } } else if (!o_ptr.is_known() && o_ptr.was_fired()) { u[n++] = "fired"; } else if (!o_ptr.flavor_is_aware() && o_ptr.flavor_was_tried()) { u[n++] = "tried"; } /* Note curses */ Object_Flag.create_mask(f2, false, Object_Flag.object_flag_type.CURSE); if (flags_known.is_inter(f2)) { u[n++] = "cursed"; } /* Note squelch */ if (Squelch.item_ok(o_ptr)) { u[n++] = "squelch"; } if (n != 0) { int i; for (i = 0; i < n; i++) { if (i == 0) { buf = buf + " {"; } buf = buf + u[i]; if (i < n - 1) { buf += ", "; } } buf += "}"; } return(end); }
/** * Describes item `o_ptr` into buffer `buf` of size `max`. * * ODESC_PREFIX prepends a 'the', 'a' or number * ODESC_BASE results in a base description. * ODESC_COMBAT will add to-hit, to-dam and AC info. * ODESC_EXTRA will add pval/charge/inscription/squelch info. * ODESC_PLURAL will pluralise regardless of the number in the stack. * ODESC_STORE turns off squelch markers, for in-store display. * ODESC_SPOIL treats the object as fully identified. * * Setting 'prefix' to true prepends a 'the', 'a' or the number in the stack, * respectively. * * \returns The number of bytes used of the buffer. */ public string object_desc(Detail mode) { bool prefix = (int)(mode & Detail.PREFIX) != 0; bool spoil = (int)(mode & Detail.SPOIL) != 0; int end = 0, i = 0; /* Simple description for null item */ if (tval == 0) { return("(nothing)"); } bool known = is_known() || (ident & Object.IDENT_STORE) != 0 || spoil; /* We've seen it at least once now we're aware of it */ if (known && ego != null && !spoil) { ego.everseen = true; } /*** Some things get really simple descriptions ***/ if (tval == TVal.TV_GOLD) { return(pval[Misc.DEFAULT_PVAL] + " gold pieces worth of " + kind.Name + (Squelch.item_ok(this) ? " {squelch}" : "")); } /** Construct the name **/ /* Copy the base name to the buffer */ string buf = ""; end = obj_desc_name(ref buf, 80, end, this, prefix, mode, spoil); if ((mode & Detail.COMBAT) != 0) { if (tval == TVal.TV_CHEST) { end = obj_desc_chest(this, ref buf, 80, end); } else if (tval == TVal.TV_LIGHT) { end = obj_desc_light(this, ref buf, 80, end); } end = obj_desc_combat(this, ref buf, 80, end, spoil); } if ((mode & Detail.EXTRA) != 0) { for (i = 0; i < num_pvals; i++) { if (spoil || this_pval_is_visible(i)) { end = obj_desc_pval(this, buf, 80, end, spoil); break; } } end = obj_desc_charges(this, ref buf, 80, end); if ((mode & Detail.STORE) != 0) { end = obj_desc_aware(this, ref buf, 80, end); } else { end = obj_desc_inscrip(this, ref buf, 80, end); } } return(buf); }
/* * This function updates the monster record of the given monster * * This involves extracting the distance to the player (if requested), * and then checking for visibility (natural, infravision, see-invis, * telepathy), updating the monster visibility flag, redrawing (or * erasing) the monster when its visibility changes, and taking note * of any interesting monster flags (cold-blooded, invisible, etc). * * Note the new "mflag" field which encodes several monster state flags, * including "view" for when the monster is currently in line of sight, * and "mark" for when the monster is currently visible via detection. * * The only monster fields that are changed here are "cdis" (the * distance from the player), "ml" (visible to the player), and * "mflag" (to maintain the "MFLAG_VIEW" flag). * * Note the special "update_monsters()" function which can be used to * call this function once for every monster. * * Note the "full" flag which requests that the "cdis" field be updated, * this is only needed when the monster (or the player) has moved. * * Every time a monster moves, we must call this function for that * monster, and update the distance, and the visibility. Every time * the player moves, we must call this function for every monster, and * update the distance, and the visibility. Whenever the player "state" * changes in certain ways ("blindness", "infravision", "telepathy", * and "see invisible"), we must call this function for every monster, * and update the visibility. * * Routines that change the "illumination" of a grid must also call this * function for any monster in that grid, since the "visibility" of some * monsters may be based on the illumination of their grid. * * Note that this function is called once per monster every time the * player moves. When the player is running, this function is one * of the primary bottlenecks, along with "update_view()" and the * "process_monsters()" code, so efficiency is important. * * Note the optimized "inline" version of the "distance()" function. * * A monster is "visible" to the player if (1) it has been detected * by the player, (2) it is close to the player and the player has * telepathy, or (3) it is close to the player, and in line of sight * of the player, and it is "illuminated" by some combination of * infravision, torch light, or permanent light (invisible monsters * are only affected by "light" if the player can see invisible). * * Monsters which are not on the current panel may be "visible" to * the player, and their descriptions will include an "offscreen" * reference. Currently, offscreen monsters cannot be targeted * or viewed directly, but old targets will remain set. XXX XXX * * The player can choose to be disturbed by several things, including * "OPT(disturb_move)" (monster which is viewable moves in some way), and * "OPT(disturb_near)" (monster which is "easily" viewable moves in some * way). Note that "moves" includes "appears" and "disappears". */ public static void update_mon(int m_idx, bool full) { Monster m_ptr = Cave.cave_monster(Cave.cave, m_idx); Monster_Race r_ptr = Misc.r_info[m_ptr.r_idx]; Monster_Lore l_ptr = Misc.l_list[m_ptr.r_idx]; if (l_ptr == null) { l_ptr = Misc.l_list[m_ptr.r_idx] = new Monster_Lore(); } int d; /* Current location */ int fy = m_ptr.fy; int fx = m_ptr.fx; /* Seen at all */ bool flag = false; /* Seen by vision */ bool easy = false; /* Compute distance */ if (full) { int py = Misc.p_ptr.py; int px = Misc.p_ptr.px; /* Distance components */ int dy = (py > fy) ? (py - fy) : (fy - py); int dx = (px > fx) ? (px - fx) : (fx - px); /* Approximate distance */ d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)); /* Restrict distance */ if (d > 255) { d = 255; } /* Save the distance */ m_ptr.cdis = (byte)d; } /* Extract distance */ else { /* Extract the distance */ d = m_ptr.cdis; } /* Detected */ if ((m_ptr.mflag & (Monster_Flag.MFLAG_MARK)) != 0) { flag = true; } /* Nearby */ if (d <= Misc.MAX_SIGHT) { /* Basic telepathy */ if (Misc.p_ptr.check_state(Object_Flag.TELEPATHY, Misc.p_ptr.state.flags)) { /* Empty mind, no telepathy */ if (r_ptr.flags.has(Monster_Flag.EMPTY_MIND.value)) { /* Nothing! */ } /* Weird mind, occasional telepathy */ else if (r_ptr.flags.has(Monster_Flag.WEIRD_MIND.value)) { throw new NotImplementedException(); ///* One in ten individuals are detectable */ //if ((m_idx % 10) == 5) //{ // /* Detectable */ // flag = true; // /* Check for LOS so that MFLAG_VIEW is set later */ // if (player_has_los_bold(fy, fx)) easy = true; //} } /* Normal mind, allow telepathy */ else { throw new NotImplementedException(); ///* Detectable */ //flag = true; ///* Check for LOS to that MFLAG_VIEW is set later */ //if (player_has_los_bold(fy, fx)) easy = true; } } /* Normal line of sight and player is not blind */ if (Cave.player_has_los_bold(fy, fx) && Misc.p_ptr.timed[(int)Timed_Effect.BLIND] == 0) { /* Use "infravision" */ if (d <= Misc.p_ptr.state.see_infra) { /* Learn about warm/cold blood */ l_ptr.flags.on(Monster_Flag.COLD_BLOOD.value); /* Handle "warm blooded" monsters */ if (!r_ptr.flags.has(Monster_Flag.COLD_BLOOD.value)) { /* Easy to see */ easy = flag = true; } } /* See if the monster is emitting light */ /*if (rf_has(r_ptr.flags, RF_HAS_LIGHT)) easy = flag = true;*/ /* Use "illumination" */ if (Cave.player_can_see_bold(fy, fx)) { /* Learn it emits light */ l_ptr.flags.on(Monster_Flag.HAS_LIGHT.value); /* Learn about invisibility */ l_ptr.flags.on(Monster_Flag.INVISIBLE.value); /* Handle "invisible" monsters */ if (r_ptr.flags.has(Monster_Flag.INVISIBLE.value)) { /* See invisible */ if (Misc.p_ptr.check_state(Object_Flag.SEE_INVIS, Misc.p_ptr.state.flags)) { /* Easy to see */ easy = flag = true; } } /* Handle "normal" monsters */ else { /* Easy to see */ easy = flag = true; } } } } /* If a mimic looks like a squelched item, it's not seen */ if (is_mimicking(m_idx)) { throw new NotImplementedException(); //object_type *o_ptr = object_byid(m_ptr.mimicked_o_idx); //if (squelch_item_ok(o_ptr)) // easy = flag = false; } /* The monster is now visible */ if (flag) { /* Learn about the monster's mind */ if (Misc.p_ptr.check_state(Object_Flag.TELEPATHY, Misc.p_ptr.state.flags)) { l_ptr.flags.set(Monster_Flag.EMPTY_MIND.value, Monster_Flag.WEIRD_MIND.value, Monster_Flag.SMART.value, Monster_Flag.STUPID.value); } /* It was previously unseen */ if (!m_ptr.ml) { /* Mark as visible */ m_ptr.ml = true; /* Draw the monster */ Cave.cave_light_spot(Cave.cave, fy, fx); /* Update health bar as needed */ if (Misc.p_ptr.health_who == m_idx) { Misc.p_ptr.redraw |= (Misc.PR_HEALTH); } /* Hack -- Count "fresh" sightings */ if (l_ptr.sights < short.MaxValue) { l_ptr.sights++; } /* Disturb on appearance */ if (Option.disturb_move.value) { Cave.disturb(Misc.p_ptr, 1, 0); } /* Window stuff */ Misc.p_ptr.redraw |= Misc.PR_MONLIST; } } /* The monster is not visible */ else { /* It was previously seen */ if (m_ptr.ml) { /* Treat mimics differently */ if (m_ptr.mimicked_o_idx == 0 || Squelch.item_ok(Object.Object.byid(m_ptr.mimicked_o_idx))) { /* Mark as not visible */ m_ptr.ml = false; /* Erase the monster */ Cave.cave_light_spot(Cave.cave, fy, fx); /* Update health bar as needed */ if (Misc.p_ptr.health_who == m_idx) { Misc.p_ptr.redraw |= (Misc.PR_HEALTH); } /* Disturb on disappearance */ if (Option.disturb_move.value) { Cave.disturb(Misc.p_ptr, 1, 0); } /* Window stuff */ Misc.p_ptr.redraw |= Misc.PR_MONLIST; } } } /* The monster is now easily visible */ if (easy) { /* Change */ if ((m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) == 0) { /* Mark as easily visible */ m_ptr.mflag |= (Monster_Flag.MFLAG_VIEW); /* Disturb on appearance */ if (Option.disturb_near.value) { Cave.disturb(Misc.p_ptr, 1, 0); } /* Re-draw monster window */ Misc.p_ptr.redraw |= Misc.PR_MONLIST; } } /* The monster is not easily visible */ else { /* Change */ if ((m_ptr.mflag & (Monster_Flag.MFLAG_VIEW)) != 0) { /* Mark as not easily visible */ m_ptr.mflag &= ~(Monster_Flag.MFLAG_VIEW); /* Disturb on disappearance */ if (Option.disturb_near.value) { Cave.disturb(Misc.p_ptr, 1, 0); } /* Re-draw monster list window */ Misc.p_ptr.redraw |= Misc.PR_MONLIST; } } }