--- deliantra/server/common/treasure.C 2010/04/25 07:08:57 1.107
+++ deliantra/server/common/treasure.C 2018/11/27 18:50:22 1.123
@@ -1,24 +1,25 @@
/*
* This file is part of Deliantra, the Roguelike Realtime MMORPG.
- *
- * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
+ *
+ * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
+ * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
* Copyright (©) 2002 Mark Wedel & Crossfire Development Team
* Copyright (©) 1992 Frank Tore Johansen
- *
+ *
* Deliantra is free software: you can redistribute it and/or modify it under
* the terms of the Affero GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the Affero GNU General Public License
* and the GNU General Public License along with this program. If not, see
* .
- *
+ *
* The authors can be reached via e-mail to
*/
@@ -36,19 +37,25 @@
#include
#include
+#include
+
+// used only by treasure.C, does not handle null arch ptrs
+#define IS_ARCH(arch,name) ((arch)->archname == shstr_ ## name)
+
extern char *spell_mapping[];
static treasurelist *first_treasurelist;
static void change_treasure (treasure *t, object *op); /* overrule default values */
-typedef std::tr1::unordered_map<
- const char *,
- treasurelist *,
- str_hash,
- str_equal,
- slice_allocator< std::pair >
-> tl_map_t;
+typedef ska::flat_hash_map
+ <
+ const char *,
+ treasurelist *,
+ str_hash,
+ str_equal,
+ slice_allocator< std::pair >
+ > tl_map_t;
static tl_map_t tl_map;
@@ -492,7 +499,7 @@
{ 0, 0, 0, 0, 100}, // 31
};
-/* calculate the appropriate level for wands staves and scrolls.
+/* calculate the appropriate level for wands staves and scrolls.
* This code presumes that op has had its spell object created (in op->inv)
*
* elmex Wed Aug 9 17:44:59 CEST 2006:
@@ -777,6 +784,29 @@
return 0;
}
+static double
+value_factor_from_spell_item (object *spell, object *item)
+{
+ double factor =
+ pow ((spell->value > 0 ? spell->value : 1)
+ * spell->level, 1.5);
+
+ if (item) // this if for: wands/staffs/rods:
+ {
+ /* Old crossfire comment ahead:
+ * Add 50 to both level an divisor to keep prices a little more
+ * reasonable. Otherwise, a high level version of a low level
+ * spell can be worth tons a money (eg, level 20 rod, level 2 spell =
+ * 10 time multiplier). This way, the value are a bit more reasonable.
+ */
+
+ factor *= item->level + 50;
+ factor /= item->inv->level + 50;
+ }
+
+ return factor;
+}
+
#define DICE2 (get_magic(2) == 2 ? 2 : 1)
#define DICESPELL (rndm (3) + rndm (3) + rndm (3) + rndm (3) + rndm (3))
@@ -787,8 +817,8 @@
*/
/* 4/28/96 added creator object from which op may now inherit properties based on
- * op->type. Right now, which stuff the creator passes on is object type
- * dependant. I know this is a spagetti manuever, but is there a cleaner
+ * op->type. Right now, which stuff the creator passes on is object type
+ * dependant. I know this is a spagetti manuever, but is there a cleaner
* way to do this? b.t. */
/*
@@ -898,7 +928,7 @@
/* Handle healing and magic power potions */
if (op->stats.sp && !op->randomitems)
{
- object *tmp = get_archetype (spell_mapping [op->stats.sp]);
+ object *tmp = archetype::get (spell_mapping [op->stats.sp]);
insert_ob_in_ob (tmp, op);
op->stats.sp = 0;
}
@@ -926,17 +956,17 @@
case POTION:
{
- int too_many_tries = 0, is_special = 0;
+ int too_many_tries = 0;
/* Handle healing and magic power potions */
if (op->stats.sp && !op->randomitems)
{
- object *tmp = get_archetype (spell_mapping[op->stats.sp]);
+ object *tmp = archetype::get (spell_mapping[op->stats.sp]);
insert_ob_in_ob (tmp, op);
op->stats.sp = 0;
}
- while (!(is_special = special_potion (op)) && !op->inv)
+ while (!special_potion (op) && !op->inv)
{
generate_artifact (op, difficulty);
if (too_many_tries++ > 10)
@@ -1043,9 +1073,7 @@
break;
case SPELLBOOK:
- op->value *= pow ((op->inv->value > 0 ? op->inv->value : 1)
- * op->inv->level,
- 1.5);
+ op->value *= value_factor_from_spell_item (op->inv, 0);
/* add exp so learning gives xp */
op->level = op->inv->level;
@@ -1060,30 +1088,21 @@
op->stats.food = op->inv->nrof;
op->nrof = 1;
/* If the spell changes by level, choose a random level
- * for it, and adjust price. If the spell doesn't
- * change by level, just set the wand to the level of
- * the spell, and value calculation is simpler.
+ * for it.
*/
- if (op->inv->duration_modifier || op->inv->dam_modifier || op->inv->range_modifier)
- {
- op->level = level_for_item (op, difficulty);
- op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
- }
+ if (op->inv->duration_modifier
+ || op->inv->dam_modifier
+ || op->inv->range_modifier)
+ op->level = level_for_item (op, difficulty);
else
- {
- op->level = op->inv->level;
- op->value = op->value * op->inv->value;
- }
+ op->level = op->inv->level;
+
+ op->value *= value_factor_from_spell_item (op->inv, op);
break;
case ROD:
op->level = level_for_item (op, difficulty);
- /* Add 50 to both level an divisor to keep prices a little more
- * reasonable. Otherwise, a high level version of a low level
- * spell can be worth tons a money (eg, level 20 rod, level 2 spell =
- * 10 time multiplier). This way, the value are a bit more reasonable.
- */
- op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
+ op->value *= value_factor_from_spell_item (op->inv, op);
/* maxhp is used to denote how many 'charges' the rod holds before */
if (op->stats.maxhp)
@@ -1096,7 +1115,7 @@
case SCROLL:
op->level = level_for_item (op, difficulty);
- op->value = op->value * op->inv->value * (op->level + 50) / (op->inv->level + 50);
+ op->value *= value_factor_from_spell_item (op->inv, op);
/* add exp so reading them properly gives xp */
op->stats.exp = op->value / 5;
@@ -1171,7 +1190,6 @@
init_artifacts ()
{
static int has_been_inited = 0;
- char filename[MAX_BUF];
artifact *art = NULL;
artifactlist *al;
@@ -1180,8 +1198,7 @@
else
has_been_inited = 1;
- sprintf (filename, "%s/artifacts", settings.datadir);
- object_thawer f (filename);
+ object_thawer f (settings.datadir, "artifacts");
if (!f)
return;
@@ -1276,8 +1293,6 @@
LOG (llevDebug, "Artifact list type %d has %d total chance\n", al->type, al->total_chance);
#endif
}
-
- LOG (llevDebug, "done.\n");
}
/*
@@ -1288,12 +1303,7 @@
add_abilities (object *op, object *change)
{
if (change->face != blank_face)
- {
-#ifdef TREASURE_VERBOSE
- LOG (llevDebug, "add_abilities change face: %d\n", change->face);
-#endif
- op->face = change->face;
- }
+ op->face = change->face;
for (int i = 0; i < NUM_STATS; i++)
change_attr_value (&(op->stats), i, change->stats.stat (i));
@@ -1488,7 +1498,7 @@
name = tmp->name, neg = 0;
/* If we match name, then return the opposite of 'neg' */
- if (!strcmp (name, op->name) || (op->arch && !strcmp (name, op->arch->archname)))
+ if (!strcmp (name, op->arch->archname))
return !neg;
/* Set success as true, since if the match was an inverse, it means