Atrinik Server  4.0
process_treasure.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
32 #include <global.h>
33 #include <object.h>
34 
35 #include "process_treasure.h"
36 
40 #define JEWELRY_MAX_LEVEL 100
41 
60 static int
62  int difficulty,
63  treasure_affinity_t *affinity,
64  double *item_power,
65  int bonus,
66  double diff_scale)
67 {
68  HARD_ASSERT(op != NULL);
69  HARD_ASSERT(item_power != NULL);
70 
71  int tmp = 5;
72  tmp += difficulty * (diff_scale * FABS(bonus));
73  tmp *= 1.0 + (0.15 * FABS(bonus));
74  tmp += rndm(0, difficulty * (diff_scale * FABS(bonus)) + 0.5);
75 
76  if (bonus > 0) {
77  /* Adjust the item's level requirement. */
78  uint32_t level = op->item_level;
79  level += (double) difficulty * (0.3 + (rndm(0, 40) / 100.0));
80  op->item_level = MIN(level, JEWELRY_MAX_LEVEL);
81 
82  op->value *= 1.24 + (0.16 * bonus);
83 
84  *item_power += tmp / 50.0;
85  } else {
86  tmp = -tmp;
87  }
88 
89  return tmp;
90 }
91 
93 static bool
95  int difficulty,
96  treasure_affinity_t *affinity,
97  double *item_power,
98  int bonus)
99 {
100  HARD_ASSERT(op != NULL);
101  HARD_ASSERT(item_power != NULL);
102 
104  difficulty,
105  affinity,
106  item_power,
107  bonus,
108  0.65);
109  return true;
110 }
111 
113 static bool
115  int difficulty,
116  treasure_affinity_t *affinity,
117  double *item_power,
118  int bonus)
119 {
120  HARD_ASSERT(op != NULL);
121  HARD_ASSERT(item_power != NULL);
122 
124  difficulty,
125  affinity,
126  item_power,
127  bonus,
128  0.35);
129  return true;
130 }
131 
133 static bool
135  int difficulty,
136  treasure_affinity_t *affinity,
137  double *item_power,
138  int bonus)
139 {
140  HARD_ASSERT(op != NULL);
141  HARD_ASSERT(item_power != NULL);
142 
143  int tmp = bonus;
144 
145  if (bonus > 0 && rndm_chance(5)) {
146  op->value *= 1.3;
147  tmp++;
148  }
149 
150  op->stats.ac += tmp;
151  op->value *= 1.0 + (0.1 * FABS(bonus));
152 
153  if (tmp > 0) {
154  *item_power += tmp;
155  }
156 
157  return true;
158 }
159 
161 static bool
163  int difficulty,
164  treasure_affinity_t *affinity,
165  double *item_power,
166  int bonus)
167 {
168  HARD_ASSERT(op != NULL);
169  HARD_ASSERT(item_power != NULL);
170 
171  int tmp = bonus;
172 
173  if (bonus > 0 && rndm_chance(5)) {
174  op->value *= 1.3;
175  tmp++;
176  }
177 
178  op->stats.wc += tmp;
179  op->value *= 1.0 + (0.1 * FABS(bonus));
180 
181  if (tmp > 0) {
182  *item_power += tmp;
183  }
184 
185  return true;
186 }
187 
189 static bool
191  int difficulty,
192  treasure_affinity_t *affinity,
193  double *item_power,
194  int bonus)
195 {
196  HARD_ASSERT(op != NULL);
197  HARD_ASSERT(item_power != NULL);
198 
199  int roll = difficulty / 20.0 + FABS(bonus);
200  int tmp = 10;
201 
202  for (int i = 0; i < 5; i++) {
203  tmp += rndm(0, roll);
204  }
205 
206  /* Cursed items need to have higher negative values to equal
207  * out with positive values for how protections work out. Put
208  * another little random element in since that they don't
209  * always end up with even values. */
210  if (bonus < 0) {
211  tmp = 2 * -tmp - rndm(0, roll);
212  }
213 
214  /* Upper limit */
215  if (tmp > 40) {
216  tmp = 40;
217  }
218 
219  /* Attempt to find a free protection. */
220  for (int i = 0; i < 5; i++) {
221  int idx = rndm(0, LAST_PROTECTION - 1);
222  if (op->protection[idx] != 0) {
223  continue;
224  }
225 
226  op->protection[idx] = tmp;
227 
228  if (tmp > 0) {
229  *item_power += (tmp + 10.0) / 20.0;
230  }
231 
232  return true;
233  }
234 
235  return false;
236 }
237 
244  {10, jewelry_set_bonus_ac},
245  {10, jewelry_set_bonus_wc},
247 };
248 
257 bool
259 {
260  HARD_ASSERT(op != NULL);
261 
262  /* If it has a title, it's already a special treasure item. */
263  if (op->title != NULL) {
264  return true;
265  }
266 
267  return false;
268 }
269 
280 uint32_t
282  size_t table_size)
283 {
284  HARD_ASSERT(table != NULL);
285  HARD_ASSERT(table_size != 0);
286 
287  uint32_t total_chance = 0;
288  for (size_t i = 0; i < table_size; i++) {
289  total_chance += table[i].chance;
290  }
291 
292  /* We need to have *some* total chance. */
293  HARD_ASSERT(total_chance != 0);
294 
295  return total_chance;
296 }
297 
307 static int
309 {
310 #define DIFFICULTY_BONUS_ROLLS 40
311 #define DIFFICULTY_BONUS_CHANCE 5
312 
313  int bonus = 1;
314  if (difficulty < DIFFICULTY_BONUS_ROLLS) {
315  return bonus;
316  }
317 
318  /* Essentially, for every X difficulty levels we add a chance for some
319  * amount of bonus rolls. */
320  int bonus_rolls = rndm(0, difficulty / DIFFICULTY_BONUS_ROLLS);
321  for (int i = 0; i < bonus_rolls; i++) {
322  /* Only apply the bonus if we're lucky enough. */
323  if (rndm_chance(DIFFICULTY_BONUS_CHANCE)) {
324  bonus++;
325  }
326  }
327 
328  return bonus;
329 
330 #undef DIFFICULTY_BONUS_ROLLS
331 #undef DIFFICULTY_BONUS_CHANCE
332 }
333 
352 static bool
354  object *op,
355  int difficulty,
356  treasure_affinity_t *affinity,
357  double *item_power,
358  int bonus)
359 {
360  HARD_ASSERT(entry != NULL);
361  HARD_ASSERT(op != NULL);
362  HARD_ASSERT(item_power != NULL);
363 
364  if (!entry->set_bonus_func(op,
365  difficulty,
366  affinity,
367  item_power,
368  bonus)) {
369  return false;
370  }
371 
372  op->value = (double) op->value * 2.0 * (1.0 + 0.45 * FABS(bonus));
373 
374  if (bonus < 0) {
375  op->value /= 2;
376  }
377 
378  if (op->value < 0) {
379  op->value = 0;
380  }
381 
382  return true;
383 }
384 
407 bool
409  size_t table_size,
410  uint32_t total_chance,
411  object *op,
412  int difficulty,
413  treasure_affinity_t *affinity,
414  double *item_power)
415 {
416 #define MAX_BONUS_TRIES 100
417 
418  HARD_ASSERT(table != NULL);
419  HARD_ASSERT(table_size > 1);
420  HARD_ASSERT(op != NULL);
421  HARD_ASSERT(item_power != NULL);
422 
423  int bonus;
424  if (op->type == AMULET || op->type == RING) {
425  bonus = process_treasure_get_jewelry_bonus(difficulty);
426  } else {
427  log_error("Cannot get item type bonus for type: %u",
428  op->type);
429  return false;
430  }
431 
433 
434  if (QUERY_FLAG(op, FLAG_CURSED)) {
435  bonus = -bonus;
436  } else if (QUERY_FLAG(op, FLAG_DAMNED)) {
437  bonus = -(bonus * 2);
438  }
439 
440  for (int attempt = 0; attempt < MAX_BONUS_TRIES; attempt++) {
441  int roll = rndm(0, total_chance - 1);
442 
443  for (size_t i = 0; i < table_size; i++) {
444  roll -= table[i].chance;
445  if (roll < 0) {
446  if (process_treasure_table_set_bonus(&table[i],
447  op,
448  difficulty,
449  affinity,
450  item_power,
451  bonus)) {
452  return true;
453  }
454 
455  /* Failed to set a bonus, so attempt to roll hopefully a
456  * different one. */
457  break;
458  }
459  }
460 
461  if (roll >= 0) {
462  log_error("Roll has %d remaining, total chance: %d",
463  roll,
464  total_chance);
465  return false;
466  }
467  }
468 
469  log_error("Failed to set bonus for treasure: %s",
470  object_get_str(op));
471  return false;
472 
473 #undef MAX_BONUS_TRIES
474 }
475 
492 bool
494  int difficulty,
495  treasure_affinity_t *affinity,
496  double *item_power)
497 {
498  static uint32_t total_chance = 0;
499  if (total_chance == 0) {
500  total_chance =
501  PROCESS_TREASURE_TABLE_TOTAL_CHANCE(jewelry_treasure_table);
502  }
503 
504  return process_treasure_table(jewelry_treasure_table,
505  arraysize(jewelry_treasure_table),
506  total_chance,
507  op,
508  difficulty,
509  affinity,
510  item_power);
511 }
512 
521 void
523  double item_power)
524 {
525  HARD_ASSERT(op != NULL);
526 
527  int tmp = (int) item_power;
528  if (tmp < INT8_MIN) {
529  tmp = INT8_MIN;
530  } else if (tmp > INT8_MAX) {
531  tmp = INT8_MAX;
532  }
533 
534  op->item_power += tmp;
535 }
536 
static bool jewelry_set_bonus_wc(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
int16_t ac
Definition: living.h:93
uint8_t item_level
Definition: object.h:375
#define FLAG_CURSED
Definition: define.h:1154
bool process_treasure_table_jewelry(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power)
#define JEWELRY_MAX_LEVEL
static bool jewelry_set_bonus_ac(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
void process_treasure_set_item_power(object *op, double item_power)
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
int16_t maxsp
Definition: living.h:81
static bool jewelry_set_bonus_protect(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
const char * title
Definition: object.h:171
#define FLAG_DAMNED
Definition: define.h:1158
int32_t maxhp
Definition: living.h:75
const char * object_get_str(const object *op)
Definition: object.c:3151
static int jewelry_set_bonus_max_hpsp(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus, double diff_scale)
bool process_treasure_table(const process_treasure_table_t *table, size_t table_size, uint32_t total_chance, object *op, int difficulty, treasure_affinity_t *affinity, double *item_power)
uint32_t process_treasure_table_total_chance(const process_treasure_table_t *table, size_t table_size)
#define SET_FLAG(xyz, p)
Definition: define.h:741
static int process_treasure_get_jewelry_bonus(int difficulty)
int8_t item_power
Definition: object.h:442
#define PROCESS_TREASURE_TABLE_TOTAL_CHANCE(table)
static bool process_treasure_table_set_bonus(const process_treasure_table_t *entry, object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
int16_t wc
Definition: living.h:90
int8_t protection[NROFATTACKS]
Definition: object.h:439
bool process_treasure_is_special(object *op)
#define RING
Definition: define.h:320
living stats
Definition: object.h:481
bool(* set_bonus_func)(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
uint8_t type
Definition: object.h:360
static bool jewelry_set_bonus_maxhp(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
#define LAST_PROTECTION
Definition: attack.h:94
#define FLAG_IS_MAGICAL
Definition: define.h:1129
static const process_treasure_table_t jewelry_treasure_table[]
static bool jewelry_set_bonus_maxsp(object *op, int difficulty, treasure_affinity_t *affinity, double *item_power, int bonus)
#define AMULET
Definition: define.h:234
int64_t value
Definition: object.h:240