--- 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