Atrinik Server  4.0
scroll.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 <player.h>
34 #include <object.h>
35 #include <object_methods.h>
36 #include <artifact.h>
37 
39 
41 static int
42 apply_func (object *op, object *applier, int aflags)
43 {
44  HARD_ASSERT(op != NULL);
45  HARD_ASSERT(applier != NULL);
46 
47  if (QUERY_FLAG(applier, FLAG_BLIND)) {
48  draw_info(COLOR_WHITE, applier, "You are unable to read while blind.");
49  return OBJECT_METHOD_OK;
50  }
51 
52  if (!QUERY_FLAG(op, FLAG_IDENTIFIED)) {
53  identify(op);
54  }
55 
56  if (op->stats.sp < 0 || op->stats.sp >= NROFREALSPELLS) {
57  draw_info(COLOR_WHITE, applier,
58  "The scroll just doesn't make sense!");
59  return OBJECT_METHOD_OK;
60  }
61 
62  if (applier->type == PLAYER) {
63  /* Players need a literacy skill to read scrolls. */
64  if (!change_skill(applier, SK_LITERACY)) {
65  draw_info(COLOR_WHITE, applier,
66  "You are unable to decipher the strange symbols.");
67  return OBJECT_METHOD_OK;
68  }
69 
70  /* Also need the appropriate skill for the scroll's spell. */
71  if (!change_skill(applier, SK_WIZARDRY_SPELLS)) {
72  draw_info(COLOR_WHITE, applier,
73  "You can read the scroll but you don't understand it.");
74  return OBJECT_METHOD_OK;
75  }
76 
77  CONTR(applier)->stat_scrolls_used++;
78  }
79 
80  draw_info_format(COLOR_WHITE, applier,
81  "The scroll of %s turns to dust.",
82  spells[op->stats.sp].name);
83 
84  int direction = applier->direction ? applier->direction : SOUTHEAST;
85  cast_spell(applier,
86  op,
87  direction,
88  op->stats.sp,
89  0,
91  NULL);
92  decrease_ob(op);
93 
94  return OBJECT_METHOD_OK;
95 }
96 
98 static int
100  object **ret,
101  int difficulty,
102  treasure_affinity_t *affinity,
103  int flags)
104 {
105  HARD_ASSERT(op != NULL);
106  HARD_ASSERT(difficulty > 0);
107 
108  /* Avoid processing if the item is already special. */
109  if (process_treasure_is_special(op)) {
111  }
112 
113  /* Attempt to generate an artifact. */
114  for (int tries = 0; op->stats.sp == SP_NO_SPELL; tries++) {
115  /* Give it a few tries. */
116  if (tries >= 5) {
117  log_error("Failed to generate a spell for scroll: %s",
118  object_get_str(op));
119  object_remove(op, 0);
120  object_destroy(op);
121  return OBJECT_METHOD_ERROR;
122  }
123 
124  artifact_generate(op, difficulty, affinity);
125  }
126 
128 
129  /* Calculate the level. Essentially -20 below the difficulty at worst, or
130  * +15 above the difficulty at best. */
131  int level = difficulty - 20 + rndm(0, 35);
132  level = MIN(MAX(level, 1), MAXLEVEL);
133  op->level = level;
134 
135  return OBJECT_METHOD_OK;
136 }
137 
142 {
143  OBJECT_METHODS(SCROLL)->apply_func = apply_func;
144  OBJECT_METHODS(SCROLL)->process_treasure_func = process_treasure_func;
145  OBJECT_METHODS(SCROLL)->override_treasure_processing = true;
146 }
#define SCROLL
Definition: define.h:453
void object_destroy(object *ob)
Definition: object.c:1441
void identify(object *op)
Definition: item.c:1364
#define NROFREALSPELLS
Definition: define.h:664
#define OBJECT_METHOD_ERROR
#define FLAG_BLIND
Definition: define.h:884
#define PLAYER
Definition: define.h:122
int16_t sp
Definition: living.h:78
#define QUERY_FLAG(xyz, p)
Definition: define.h:761
static int apply_func(object *op, object *applier, int aflags)
Definition: scroll.c:42
void object_remove(object *op, int flags)
Definition: object.c:1623
int cast_spell(object *op, object *caster, int dir, int type, int ability, int item, const char *stringarg)
Definition: spell_util.c:192
#define decrease_ob(xyz)
Definition: object.h:624
const char * object_get_str(const object *op)
Definition: object.c:3151
int8_t direction
Definition: object.h:350
#define SP_NO_SPELL
Definition: spells.h:202
#define SET_FLAG(xyz, p)
Definition: define.h:741
#define SOUTHEAST
Definition: map.h:843
int change_skill(object *who, int sk_index)
Definition: skill_util.c:340
#define CAST_SCROLL
Definition: spells.h:281
const char * name
Definition: spells.h:132
#define OBJECT_METHOD_UNHANDLED
static int process_treasure_func(object *op, object **ret, int difficulty, treasure_affinity_t *affinity, int flags)
Definition: scroll.c:99
spell_struct spells[NROFREALSPELLS]
Definition: spellist.h:34
#define MAXLEVEL
Definition: global.h:221
bool process_treasure_is_special(object *op)
living stats
Definition: object.h:481
uint8_t type
Definition: object.h:360
#define OBJECT_METHODS(type)
OBJECT_TYPE_INIT_DEFINE(scroll)
Definition: scroll.c:141
bool artifact_generate(object *op, int difficulty, treasure_affinity_t *affinity)
Definition: artifact.c:541
#define OBJECT_METHOD_OK
#define FLAG_IS_MAGICAL
Definition: define.h:1129
int8_t level
Definition: object.h:347
#define FLAG_IDENTIFIED
Definition: define.h:980