/* * 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); }
/* * Some cheap objects should be created in piles. */ static void mass_produce(Object.Object o_ptr) { int size = 1; int cost = o_ptr.value(1, false); /* Analyze the type */ switch (o_ptr.tval) { /* Food, Flasks, and Lights */ case TVal.TV_FOOD: case TVal.TV_FLASK: case TVal.TV_LIGHT: { if (cost <= 5L) size += mass_roll(3, 5); if (cost <= 20L) size += mass_roll(3, 5); break; } case TVal.TV_POTION: case TVal.TV_SCROLL: { if (cost <= 60L) size += mass_roll(3, 5); if (cost <= 240L) size += mass_roll(1, 5); break; } case TVal.TV_MAGIC_BOOK: case TVal.TV_PRAYER_BOOK: { if (cost <= 50L) size += mass_roll(2, 3); if (cost <= 500L) size += mass_roll(1, 3); break; } case TVal.TV_SOFT_ARMOR: case TVal.TV_HARD_ARMOR: case TVal.TV_SHIELD: case TVal.TV_GLOVES: case TVal.TV_BOOTS: case TVal.TV_CLOAK: case TVal.TV_HELM: case TVal.TV_CROWN: case TVal.TV_SWORD: case TVal.TV_POLEARM: case TVal.TV_HAFTED: case TVal.TV_DIGGING: case TVal.TV_BOW: { if (o_ptr.ego != null) break; if (cost <= 10L) size += mass_roll(3, 5); if (cost <= 100L) size += mass_roll(3, 5); break; } case TVal.TV_SPIKE: case TVal.TV_SHOT: case TVal.TV_ARROW: case TVal.TV_BOLT: { if (cost <= 5L) size = (int)Random.randint1(3) * 20; /* 20-60 in 20s */ else if (cost > 5L && cost <= 50L) size = (int)Random.randint1(4) * 10; /* 10-40 in 10s */ else if (cost > 50 && cost <= 500L) size = (int)Random.randint1(4) * 5; /* 5-20 in 5s */ else size = 1; break; } } /* Save the total pile size */ o_ptr.number = (byte)size; }
/* * This makes sure that the black market doesn't stock any object that other * stores have, unless it is an ego-item or has various bonuses. * * Based on a suggestion by Lee Vogt <*****@*****.**>. */ static bool black_market_ok(Object.Object o_ptr) { /* Ego items are always fine */ if (o_ptr.ego != null) return (true); /* Good items are normally fine */ if (o_ptr.to_a > 2) return (true); if (o_ptr.to_h > 1) return (true); if (o_ptr.to_d > 2) return (true); /* No cheap items */ if (o_ptr.value(1, false) < 10) return (false); /* Check the other stores */ for (int i = 0; i < (int)STORE.MAX_STORES; i++) { /* Skip home and black market */ if (i == (int)STORE.B_MARKET || i == (int)STORE.HOME) continue; /* Check every object in the store */ for (int j = 0; j < Misc.stores[i].stock_num; j++) { Object.Object j_ptr = Misc.stores[i].stock[j]; /* Compare object kinds */ if (o_ptr.kind == j_ptr.kind) return (false); } } /* Otherwise fine */ return (true); }
/* * Determine the price of an object (qty one) in a store. * * store_buying == true means the shop is buying, player selling * == false means the shop is selling, player buying * * This function takes into account the player's charisma, but * never lets a shop-keeper lose money in a transaction. * * The "greed" value should exceed 100 when the player is "buying" the * object, and should be less than 100 when the player is "selling" it. * * Hack -- the black market always charges twice as much as it should. */ public static int price_item(Object.Object o_ptr, bool store_buying, int qty) { int adjust; int price; Store store = current_store(); Owner ot_ptr; if (store == null) return 0; ot_ptr = store.owner; /* Get the value of the stack of wands, or a single item */ if ((o_ptr.tval == TVal.TV_WAND) || (o_ptr.tval == TVal.TV_STAFF)) price = o_ptr.value(qty, false); else price = o_ptr.value(1, false); /* Worthless items */ if (price <= 0) return (0); /* Add in the charisma factor */ if (store.sidx == STORE.B_MARKET) adjust = 150; else adjust = Player.Player.adj_chr_gold[Misc.p_ptr.state.stat_ind[(int)Stat.Chr]]; /* Shop is buying */ if (store_buying) { /* Set the factor */ adjust = 100 + (100 - adjust); if (adjust > 100) adjust = 100; /* Shops now pay 2/3 of true value */ price = price * 2 / 3; /* Black market sucks */ if (store.sidx == STORE.B_MARKET) price = price / 2; /* Check for no_selling option */ if (Option.birth_no_selling.value) return (0); } /* Shop is selling */ else { /* Fix the factor */ if (adjust < 100) adjust = 100; /* Black market sucks */ if (store.sidx == STORE.B_MARKET) price = price * 2; } /* Compute the final price (with rounding) */ price = (int)((price * adjust + 50L) / 100); /* Now convert price to total price for non-wands */ if (!(o_ptr.tval == TVal.TV_WAND) && !(o_ptr.tval == TVal.TV_STAFF)) price *= qty; /* Now limit the price to the purse limit */ if (store_buying && (price > ot_ptr.max_cost * qty)) price = ot_ptr.max_cost * qty; /* Note -- Never become "free" */ if (price <= 0L) return (qty); /* Return the price */ return (price); }
/* * 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; }
/* * Add an object to a real stores inventory. * * If the object is "worthless", it is thrown away (except in the home). * * If the object cannot be combined with an object already in the inventory, * make a new slot for it, and calculate its "per item" price. Note that * this price will be negative, since the price will not be "fixed" yet. * Adding an object to a "fixed" price stack will not change the fixed price. * * In all cases, return the slot (or -1) where the object was placed */ int carry(Object.Object o_ptr) { int slot; int value, j_value; Object.Object j_ptr; Object_Kind kind = o_ptr.kind; /* Evaluate the object */ value = o_ptr.value(1, false); /* Cursed/Worthless items "disappear" when sold */ if (value <= 0) return (-1); /* Erase the inscription & pseudo-ID bit */ o_ptr.note = null; /* Some item types require maintenance */ switch (o_ptr.tval) { /* Refuel lights to the standard amount */ case TVal.TV_LIGHT: { Bitflag f = new Bitflag(Object_Flag.SIZE); o_ptr.object_flags(ref f); if (!f.has(Object_Flag.NO_FUEL.value)) { if (o_ptr.sval == SVal.SV_LIGHT_TORCH) o_ptr.timeout = Misc.DEFAULT_TORCH; else if (o_ptr.sval == SVal.SV_LIGHT_LANTERN) o_ptr.timeout = Misc.DEFAULT_LAMP; } break; } /* Recharge rods */ case TVal.TV_ROD: { o_ptr.timeout = 0; break; } /* Possibly recharge wands and staves */ case TVal.TV_STAFF: case TVal.TV_WAND: { bool recharge = false; /* Recharge without fail if the store normally carries that type */ for (int i = 0; i < table_num; i++) { if (table[i] == o_ptr.kind) recharge = true; } if (recharge) { int charges = 0; /* Calculate the recharged number of charges */ for (int i = 0; i < o_ptr.number; i++) charges += Random.randcalc(kind.charge, 0, aspect.RANDOMISE); /* Use recharged value only if greater */ if (charges > o_ptr.pval[Misc.DEFAULT_PVAL]) o_ptr.pval[Misc.DEFAULT_PVAL] = (short)charges; } break; } } /* Check each existing object (try to combine) */ for (slot = 0; slot < stock_num; slot++) { /* Get the existing object */ j_ptr = stock[slot]; /* Can the existing items be incremented? */ if (j_ptr.similar(o_ptr, Object.Object.object_stack_t.OSTACK_STORE)) { /* Absorb (some of) the object */ store_object_absorb(ref j_ptr, ref o_ptr); /* All done */ return (slot); } } /* No space? */ if (stock_num >= stock_size) { return (-1); } /* Check existing slots to see if we must "slide" */ for (slot = 0; slot < stock_num; slot++) { /* Get that object */ j_ptr = stock[slot]; /* Objects sort by decreasing type */ if (o_ptr.tval > j_ptr.tval) break; if (o_ptr.tval < j_ptr.tval) continue; /* Objects sort by increasing sval */ if (o_ptr.sval < j_ptr.sval) break; if (o_ptr.sval > j_ptr.sval) continue; /* Evaluate that slot */ j_value = j_ptr.value(1, false); /* Objects sort by decreasing value */ if (value > j_value) break; if (value < j_value) continue; } /* Slide the others up */ for (int i = stock_num; i > slot; i--) { stock[i] = stock[i - 1]; /* Hack -- slide the objects */ //object_copy(&store.stock[i], &store.stock[i-1]); } /* More stuff now */ stock_num++; /* Hack -- Insert the new object */ stock[slot] = o_ptr; //object_copy(&store.stock[slot], o_ptr); /* Return the location */ return (slot); }
/* * 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); }