Crossfire Server, Trunk  1.75.0
potion.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
19 #include "global.h"
20 
21 #include <string.h>
22 
23 #include "ob_methods.h"
24 #include "ob_types.h"
25 #include "sounds.h"
26 #include "sproto.h"
27 
28 static method_ret potion_type_apply(object *potion, object *applier, int aflags);
29 
33 void init_type_potion(void) {
35 }
36 
44 static method_ret potion_type_apply(object *potion, object *applier, int aflags) {
45  int got_one = 0, i;
46  object *force;
47  (void)aflags;
48 
49  if (applier->type == PLAYER) {
50  if (!QUERY_FLAG(potion, FLAG_IDENTIFIED))
51  potion = identify(potion);
52  }
53 
54  play_sound_map(SOUND_TYPE_ITEM, applier, 0, "drink");
55  apply_handle_yield(potion);
56 
57  /* Potion of restoration - only for players */
58  if (applier->type == PLAYER && (potion->attacktype&AT_DEPLETE)) {
59  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
60  drain_stat(applier);
61  fix_object(applier);
63  return METHOD_OK;
64  }
65 
66  if (remove_depletion(applier, potion->level) == 0)
68  "Your potion had no effect.");
69 
71  return METHOD_OK;
72  }
73 
74  /* improvement potion - only for players */
75  if (applier->type == PLAYER && potion->attacktype&AT_GODPOWER) {
76  for (i = 1; i < MIN(11, applier->level); i++) {
77  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
78  if (applier->contr->levhp[i] != 1) {
79  applier->contr->levhp[i] = 1;
80  break;
81  }
82  if (applier->contr->levsp[i] != 1) {
83  applier->contr->levsp[i] = 1;
84  break;
85  }
86  if (applier->contr->levgrace[i] != 1) {
87  applier->contr->levgrace[i] = 1;
88  break;
89  }
90  } else {
91  if (applier->contr->levhp[i] < 9) {
92  applier->contr->levhp[i] = 9;
93  break;
94  }
95  if (applier->contr->levsp[i] < 6) {
96  applier->contr->levsp[i] = 6;
97  break;
98  }
99  if (applier->contr->levgrace[i] < 3) {
100  applier->contr->levgrace[i] = 3;
101  break;
102  }
103  }
104  }
105  /* Just makes checking easier */
106  if (i < MIN(11, applier->level))
107  got_one = 1;
108  if (!QUERY_FLAG(potion, FLAG_CURSED) && !QUERY_FLAG(potion, FLAG_DAMNED)) {
109  if (got_one) {
110  fix_object(applier);
112  "The Gods smile upon you and remake you a little more in their image. "
113  "You feel a little more perfect.");
114  } else
116  "The potion had no effect - you are already perfect");
117  } else { /* cursed potion */
118  if (got_one) {
119  fix_object(applier);
121  "The Gods are angry and punish you.");
122  } else
124  "You are fortunate that you are so pathetic.");
125  }
127  return METHOD_OK;
128  }
129 
130  /* A potion that casts a spell. Healing, restore spellpoint
131  * (power potion) and heroism all fit into this category.
132  * Given the spell object code, there is no limit to the number
133  * of spells that potions can be cast, but direction is
134  * problematic to try and imbue fireball potions for example.
135  */
136  if (potion->inv) {
137  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
138  object *fball;
139 
141  "Yech! Your lungs are on fire!");
142  /* Explodes a fireball centered at player */
144  fball->dam_modifier = random_roll(1, applier->level, applier, PREFER_LOW)/5+1;
145  fball->stats.maxhp = random_roll(1, applier->level, applier, PREFER_LOW)/10+2;
146  object_insert_in_map_at(fball, applier->map, NULL, 0, applier->x, applier->y);
147  } else
148  cast_spell(applier, potion, applier->facing, potion->inv, NULL);
149 
151  /* if youre dead, no point in doing this... */
152  if (!QUERY_FLAG(applier, FLAG_REMOVED))
153  fix_object(applier);
154  return METHOD_OK;
155  }
156 
157  /* Deal with protection potions */
158  force = NULL;
159  for (i = 0; i < NROFATTACKS; i++) {
160  if (potion->resist[i]) {
161  if (!force)
162  force = create_archetype(FORCE_NAME);
163  memcpy(force->resist, potion->resist, sizeof(potion->resist));
164  force->type = POTION_RESIST_EFFECT;
165  force->speed = MOVE_PER_SECOND;
166  force->duration = 60;
167  break; /* Only need to find one protection since we cappliery entire batch */
168  }
169  }
170  /* This is a protection potion */
171  if (force) {
172  char name[MAX_BUF];
173  int resist = i;
174 
175  /* cursed items last longer */
176  if (QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED)) {
177  draw_ext_info_format(NDI_RED|NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_CURSED, "The %s was cursed!", potion->name);
178  force->duration *= 10;
179  for (i = 0; i < NROFATTACKS; i++)
180  if (force->resist[i] > 0)
181  force->resist[i] = -force->resist[i]; /* prot => vuln */
182  }
183  force->speed_left = -1;
184  /* set name for expiry messages */
185  snprintf(name, MAX_BUF, "resistance to %s", change_resist_msg[resist]);
186  free_string(force->name);
187  force->name = add_string(name);
188  store_spell_expiry(force);
189  force = object_insert_in_ob(force, applier);
190  CLEAR_FLAG(potion, FLAG_APPLIED);
191  SET_FLAG(force, FLAG_APPLIED);
192  change_abil(applier, force);
194 
195  if (potion->other_arch != NULL && applier->map != NULL) {
196  object_insert_in_map_at(arch_to_object(potion->other_arch), applier->map, NULL, INS_ON_TOP, applier->x, applier->y);
197  }
198 
199  return METHOD_OK;
200  }
201 
202  /* Only thing left are the stat potions */
203  if (applier->type == PLAYER) { /* only for players */
204  if ((QUERY_FLAG(potion, FLAG_CURSED) || QUERY_FLAG(potion, FLAG_DAMNED))
205  && potion->value != 0)
206  CLEAR_FLAG(potion, FLAG_APPLIED);
207  else
208  SET_FLAG(potion, FLAG_APPLIED);
209  if (!change_abil(applier, potion))
211  "Nothing happened.");
212  }
213 
214  /* CLEAR_FLAG is so that if the character has other potions
215  * that were grouped with the one consumed, his
216  * stat will not be raised by them. fix_object just clears
217  * up all the stats.
218  */
219  CLEAR_FLAG(potion, FLAG_APPLIED);
220  fix_object(applier);
222  return METHOD_OK;
223 }
potion_type_apply
static method_ret potion_type_apply(object *potion, object *applier, int aflags)
Handles applying a potion, dust, balm, or figurine.
Definition: potion.cpp:44
PLAYER
@ PLAYER
Definition: object.h:112
global.h
SOUND_TYPE_ITEM
#define SOUND_TYPE_ITEM
Definition: newclient.h:338
living::maxhp
int16_t maxhp
Max hit points.
Definition: living.h:41
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
object::inv
object * inv
Pointer to the first object in the inventory.
Definition: object.h:298
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
cast_spell
int cast_spell(object *op, object *caster, int dir, object *spell_ob, char *stringarg)
Main dispatch when someone casts a spell.
Definition: spell_util.cpp:1424
register_apply
void register_apply(int ob_type, apply_func method)
Registers the apply method for the given type.
Definition: ob_types.cpp:62
object::speed
float speed
Frequency of object 'moves' relative to server tick rate.
Definition: object.h:337
METHOD_OK
#define METHOD_OK
Definition: ob_methods.h:15
object::x
int16_t x
Definition: object.h:335
object::speed_left
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
PREFER_LOW
#define PREFER_LOW
Definition: define.h:558
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
MSG_TYPE_APPLY_CURSED
#define MSG_TYPE_APPLY_CURSED
Applied a cursed object (BAD)
Definition: newclient.h:608
player::levhp
int8_t levhp[11]
What hp bonus the player gained on that level.
Definition: player.h:186
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
MIN
#define MIN(x, y)
Definition: compat.h:21
play_sound_map
void play_sound_map(int8_t sound_type, object *emitter, int dir, const char *action)
Plays a sound on a map.
Definition: sounds.cpp:113
player::levsp
int8_t levsp[11]
What sp bonus the player gained on that level.
Definition: player.h:187
fix_object
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
NDI_RED
#define NDI_RED
Definition: newclient.h:248
POTION_RESIST_EFFECT
@ POTION_RESIST_EFFECT
A force, holding the effect of a resistance potion.
Definition: object.h:230
NROFATTACKS
#define NROFATTACKS
Definition: attack.h:17
FLAG_APPLIED
#define FLAG_APPLIED
Object is ready for use by living.
Definition: define.h:235
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2857
object::resist
int16_t resist[NROFATTACKS]
Resistance adjustments for attacks.
Definition: object.h:351
name
Plugin animator file specs[Config] name
Definition: animfiles.txt:4
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
store_spell_expiry
void store_spell_expiry(object *spell)
Stores in the spell when to warn player of expiration.
Definition: spell_util.cpp:1981
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
object::contr
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
object_decrease_nrof_by_one
#define object_decrease_nrof_by_one(xyz)
Definition: compat.h:32
MSG_TYPE_APPLY_SUCCESS
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:606
POTION
@ POTION
Definition: object.h:116
EXPLODING_FIREBALL
#define EXPLODING_FIREBALL
This is used for fumbles - this arch is all set up to do the right just by inserting it.
Definition: spells.h:174
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
change_resist_msg
const char *const change_resist_msg[NROFATTACKS]
These are the descriptions of the resistances displayed when a player puts on/takes off an item.
Definition: init.cpp:70
object::value
int32_t value
How much money it is worth (or contains)
Definition: object.h:360
player::levgrace
int8_t levgrace[11]
What grace bonus the player gained on that level.
Definition: player.h:188
object::type
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
FLAG_DAMNED
#define FLAG_DAMNED
The object is very cursed.
Definition: define.h:317
sproto.h
random_roll
int random_roll(int min, int max, const object *op, int goodbad)
Roll a random number between min and max.
Definition: utils.cpp:42
object::facing
int8_t facing
Object is oriented/facing that way.
Definition: object.h:345
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2100
object::other_arch
struct archetype * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:425
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
INS_ON_TOP
#define INS_ON_TOP
Always put object on top.
Definition: object.h:583
create_archetype
object * create_archetype(const char *name)
Finds which archetype matches the given name, and returns a new object containing a copy of the arche...
Definition: arch.cpp:276
free_string
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.cpp:280
init_type_potion
void init_type_potion(void)
Initializer for the potion object type.
Definition: potion.cpp:33
change_abil
int change_abil(object *op, object *tmp)
Permanently alters an object's stats/flags based on another object.
Definition: living.cpp:394
method_ret
char method_ret
Define some standard return values for callbacks which don't need to return any other results.
Definition: ob_methods.h:14
ob_types.h
sounds.h
FLAG_REMOVED
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
object::dam_modifier
uint8_t dam_modifier
How going up in level affects damage.
Definition: object.h:419
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:265
apply_handle_yield
void apply_handle_yield(object *tmp)
This checks whether the object has a "on_use_yield" field, and if so generated and drops matching ite...
Definition: apply.cpp:122
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
drain_stat
void drain_stat(object *op)
Drains a random stat from op.
Definition: living.cpp:716
AT_DEPLETE
#define AT_DEPLETE
Definition: attack.h:92
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
object::duration
int16_t duration
Number of moves (see 'speed') spell lasts.
Definition: object.h:415
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
MSG_TYPE_APPLY_FAILURE
#define MSG_TYPE_APPLY_FAILURE
Apply OK, but no/bad result.
Definition: newclient.h:607
AT_GODPOWER
#define AT_GODPOWER
Definition: attack.h:96
remove_depletion
int remove_depletion(object *op, int level)
Remove depletion from op, if present, and warn player of such restorations.
Definition: living.cpp:755
ob_methods.h
object::stats
living stats
Str, Con, Dex, etc.
Definition: object.h:378
MSG_TYPE_APPLY
#define MSG_TYPE_APPLY
Applying objects.
Definition: newclient.h:411
object::attacktype
uint32_t attacktype
Bitmask of attacks this object does.
Definition: object.h:352
FLAG_CURSED
#define FLAG_CURSED
The object is cursed.
Definition: define.h:316
MOVE_PER_SECOND
static const float MOVE_PER_SECOND
Speed of an object that gives it one move per second, real time.
Definition: tod.h:54
FORCE_NAME
#define FORCE_NAME
Definition: spells.h:169
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
identify
object * identify(object *op)
Identifies an item.
Definition: item.cpp:1426