Crossfire Server, Branches 1.12  R18729
potion.c
Go to the documentation of this file.
1 /*
2  CrossFire, A Multiplayer game for X-windows
3 
4  Copyright (C) 2007 Mark Wedel & Crossfire Development Team
5  Copyright (C) 1992 Frank Tore Johansen
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  The authors can be reached via e-mail at crossfire-devel@real-time.com
22 */
26 #include <global.h>
27 #include <ob_methods.h>
28 #include <ob_types.h>
29 #include <sounds.h>
30 #include <sproto.h>
31 
32 static method_ret potion_type_apply(ob_methods *context, object *potion,
33  object *applier, int aflags);
34 
38 void init_type_potion(void) {
40 }
41 
50 static method_ret potion_type_apply(ob_methods *context, object *potion,
51  object *applier, int aflags) {
52  int got_one = 0, i;
53  object *force;
54 
55  if (applier->type == PLAYER) {
56  if (!QUERY_FLAG(potion, FLAG_IDENTIFIED))
57  identify(potion);
58  }
59 
60  handle_apply_yield(potion);
61 
62  /* Potion of restoration - only for players */
63  if (applier->type == PLAYER && (potion->attacktype&AT_DEPLETE)) {
64  object *depl;
65  archetype *at;
66 
67  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
68  drain_stat(applier);
69  fix_object(applier);
70  decrease_ob(potion);
71  return METHOD_OK;
72  }
73 
74  if ((at = find_archetype(ARCH_DEPLETION)) == NULL) {
75  LOG(llevError, "Could not find archetype depletion\n");
76  return METHOD_ERROR;
77  }
78 
79  depl = present_arch_in_ob(at, applier);
80  if (depl != NULL
81  && (potion->level != 0 && potion->level >= applier->level)) {
82  for (i = 0; i < NUM_STATS; i++)
83  if (get_attr_value(&depl->stats, i)) {
85  restore_msg[i], NULL);
86  }
87  remove_ob(depl);
88  free_object(depl);
89  fix_object(applier);
90  }
91  else
93  "You potion had no effect.", NULL);
94 
95  decrease_ob(potion);
96  return METHOD_OK;
97  }
98 
99  /* improvement potion - only for players */
100  if (applier->type == PLAYER && potion->attacktype&AT_GODPOWER) {
101  for (i = 1; i < MIN(11, applier->level); i++) {
102  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
103  if (applier->contr->levhp[i] != 1) {
104  applier->contr->levhp[i] = 1;
105  break;
106  }
107  if (applier->contr->levsp[i] != 1) {
108  applier->contr->levsp[i] = 1;
109  break;
110  }
111  if (applier->contr->levgrace[i] != 1) {
112  applier->contr->levgrace[i] = 1;
113  break;
114  }
115  } else {
116  if (applier->contr->levhp[i] < 9) {
117  applier->contr->levhp[i] = 9;
118  break;
119  }
120  if (applier->contr->levsp[i] < 6) {
121  applier->contr->levsp[i] = 6;
122  break;
123  }
124  if (applier->contr->levgrace[i] < 3) {
125  applier->contr->levgrace[i] = 3;
126  break;
127  }
128  }
129  }
130  /* Just makes checking easier */
131  if (i < MIN(11, applier->level))
132  got_one = 1;
133  if (!QUERY_FLAG(potion, FLAG_CURSED) && !QUERY_FLAG(potion, FLAG_DAMNED)) {
134  if (got_one) {
135  fix_object(applier);
137  "The Gods smile upon you and remake you a little more in their image."
138  "You feel a little more perfect.", NULL);
139  } else
141  "The potion had no effect - you are already perfect", NULL);
142  } else { /* cursed potion */
143  if (got_one) {
144  fix_object(applier);
146  "The Gods are angry and punish you.", NULL);
147  } else
149  "You are fortunate that you are so pathetic.", NULL);
150  }
151  decrease_ob(potion);
152  return METHOD_OK;
153  }
154 
155  /* A potion that casts a spell. Healing, restore spellpoint
156  * (power potion) and heroism all fit into this category.
157  * Given the spell object code, there is no limit to the number
158  * of spells that potions can be cast, but direction is
159  * problematic to try and imbue fireball potions for example.
160  */
161  if (potion->inv) {
162  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
163  object *fball;
164 
166  "Yech! Your lungs are on fire!", NULL);
167  /* Explodes a fireball centered at player */
169  fball->dam_modifier = random_roll(1, applier->level, applier, PREFER_LOW)/5+1;
170  fball->stats.maxhp = random_roll(1, applier->level, applier, PREFER_LOW)/10+2;
171  fball->x = applier->x;
172  fball->y = applier->y;
173  insert_ob_in_map(fball, applier->map, NULL, 0);
174  } else
175  cast_spell(applier, potion, applier->facing, potion->inv, NULL);
176 
177  decrease_ob(potion);
178  /* if youre dead, no point in doing this... */
179  if (!QUERY_FLAG(applier, FLAG_REMOVED))
180  fix_object(applier);
181  return METHOD_OK;
182  }
183 
184  /* Deal with protection potions */
185  force = NULL;
186  for (i = 0; i < NROFATTACKS; i++) {
187  if (potion->resist[i]) {
188  if (!force)
189  force = create_archetype(FORCE_NAME);
190  memcpy(force->resist, potion->resist, sizeof(potion->resist));
191  force->type = POTION_EFFECT;
192  break; /* Only need to find one protection since we cappliery entire batch */
193  }
194  }
195  /* This is a protection potion */
196  if (force) {
197  /* cursed items last longer */
198  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
199  force->stats.food *= 10;
200  for (i = 0; i < NROFATTACKS; i++)
201  if (force->resist[i] > 0)
202  force->resist[i] = -force->resist[i]; /* prot => vuln */
203  }
204  force->speed_left = -1;
205  force = insert_ob_in_ob(force, applier);
206  CLEAR_FLAG(potion, FLAG_APPLIED);
207  SET_FLAG(force, FLAG_APPLIED);
208  change_abil(applier, force);
209  decrease_ob(potion);
210  return METHOD_OK;
211  }
212 
213  /* Only thing left are the stat potions */
214  if (applier->type == PLAYER) { /* only for players */
215  if ((QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED))
216  && potion->value != 0)
217  CLEAR_FLAG(potion, FLAG_APPLIED);
218  else
219  SET_FLAG(potion, FLAG_APPLIED);
220  if (!change_abil(applier, potion))
222  "Nothing happened.", NULL);
223  }
224 
225  /* CLEAR_FLAG is so that if the character has other potions
226  * that were grouped with the one consumed, his
227  * stat will not be raised by them. fix_object just clears
228  * up all the stats.
229  */
230  CLEAR_FLAG(potion, FLAG_APPLIED);
231  fix_object(applier);
232  decrease_ob(potion);
233  return METHOD_OK;
234 }
archetype * find_archetype(const char *name)
Definition: arch.c:700
#define FLAG_DAMNED
Definition: define.h:614
void drain_stat(object *op)
Definition: living.c:748
#define AT_DEPLETE
Definition: attack.h:120
const char *const restore_msg[NUM_STATS]
Definition: living.c:240
#define SET_FLAG(xyz, p)
Definition: define.h:510
#define MSG_TYPE_APPLY_FAILURE
Definition: newclient.h:519
#define METHOD_ERROR
Definition: ob_methods.h:44
static method_ret potion_type_apply(ob_methods *context, object *potion, object *applier, int aflags)
Definition: potion.c:50
#define EXPLODING_FIREBALL
Definition: spells.h:201
sint8 get_attr_value(const living *stats, int attr)
Definition: living.c:377
#define PREFER_LOW
Definition: define.h:909
#define POTION
Definition: define.h:117
void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *message, const char *oldmessage)
Definition: standalone.c:171
sint16 x
Definition: object.h:179
sint8 levsp[11]
Definition: player.h:219
Definition: object.h:321
uint8 dam_modifier
Definition: object.h:258
#define PLAYER
Definition: define.h:113
#define POTION_EFFECT
Definition: define.h:297
#define FLAG_REMOVED
Definition: define.h:528
char method_ret
Definition: ob_methods.h:41
int change_abil(object *op, object *tmp)
Definition: living.c:443
void remove_ob(object *op)
Definition: object.c:1515
sint16 maxhp
Definition: living.h:82
#define AT_GODPOWER
Definition: attack.h:124
void handle_apply_yield(object *tmp)
Definition: apply.c:131
object * create_archetype(const char *name)
Definition: arch.c:625
float speed_left
Definition: object.h:182
#define METHOD_OK
Definition: ob_methods.h:42
struct mapdef * map
Definition: object.h:155
#define ARCH_DEPLETION
Definition: object.h:405
#define FLAG_IDENTIFIED
Definition: define.h:557
void identify(object *op)
Definition: item.c:1447
#define MSG_TYPE_ATTRIBUTE
Definition: newclient.h:327
sint8 facing
Definition: object.h:186
sint16 y
Definition: object.h:179
void register_apply(int ob_type, apply_func method)
Definition: ob_types.c:79
struct pl * contr
Definition: object.h:134
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
#define CLEAR_FLAG(xyz, p)
Definition: define.h:512
#define MSG_TYPE_APPLY
Definition: newclient.h:330
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
#define MIN(x, y)
Definition: define.h:67
sint16 resist[NROFATTACKS]
Definition: object.h:192
#define MSG_TYPE_APPLY_CURSED
Definition: newclient.h:520
#define FLAG_CURSED
Definition: define.h:613
#define decrease_ob(xyz)
Definition: global.h:276
#define MSG_TYPE_APPLY_SUCCESS
Definition: newclient.h:518
uint32 attacktype
Definition: object.h:193
#define NUM_STATS
Definition: living.h:48
living stats
Definition: object.h:219
object * present_arch_in_ob(const archetype *at, const object *op)
Definition: object.c:2859
sint8 levgrace[11]
Definition: player.h:220
#define FLAG_APPLIED
Definition: define.h:531
#define NROFATTACKS
Definition: attack.h:45
#define FORCE_NAME
Definition: spells.h:196
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
sint8 levhp[11]
Definition: player.h:218
void free_object(object *ob)
Definition: object.c:1238
int random_roll(int min, int max, const object *op, int goodbad)
Definition: utils.c:51
void init_type_potion(void)
Definition: potion.c:38
sint16 level
Definition: object.h:202
void fix_object(object *op)
Definition: living.c:900
sint32 value
Definition: object.h:201
#define MSG_TYPE_ATTRIBUTE_STAT_GAIN
Definition: newclient.h:482
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Definition: spell_util.c:1308
uint8 type
Definition: object.h:189
sint32 food
Definition: living.h:89