ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/skills.C
(Generate patch)

Comparing deliantra/server/server/skills.C (file contents):
Revision 1.7 by root, Sun Sep 3 00:18:42 2006 UTC vs.
Revision 1.11 by root, Sat Sep 16 22:24:13 2006 UTC

1/*
2 * static char *rcsid_skills_c =
3 * "$Id: skills.C,v 1.7 2006/09/03 00:18:42 root Exp $";
4 */
5/* 1/*
6 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
7 3
8 Copyright (C) 2003 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2003 Mark Wedel & Crossfire Development Team
9 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
20 16
21 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 20
25 The authors can be reached via e-mail to crossfire-devel@real-time.com 21 The authors can be reached via e-mail to <crossfire@schmorp.de>
26*/ 22*/
27 23
28#include <global.h> 24#include <global.h>
29#include <object.h> 25#include <object.h>
30#ifndef __CEXTRACT__ 26#ifndef __CEXTRACT__
31#include <sproto.h> 27# include <sproto.h>
32#endif 28#endif
33#include <living.h> 29#include <living.h>
34#include <skills.h> 30#include <skills.h>
35#include <spells.h> 31#include <spells.h>
36#include <book.h> 32#include <book.h>
37 33
38/* adj_stealchance() - increased values indicate better attempts */ 34/* adj_stealchance() - increased values indicate better attempts */
35static int
39static int adj_stealchance (object *op, object *victim, int roll) { 36adj_stealchance (object *op, object *victim, int roll)
37{
40 object *equip; 38 object *equip;
41 39
42 if(!op||!victim||!roll) return -1; 40 if (!op || !victim || !roll)
41 return -1;
43 42
44 /* Only prohibit stealing if the player does not have a free 43 /* Only prohibit stealing if the player does not have a free
45 * hand available and in fact does have hands. 44 * hand available and in fact does have hands.
46 */ 45 */
47 if(op->type==PLAYER && op->body_used[BODY_ARMS] <=0 && 46 if (op->type == PLAYER && op->body_used[BODY_ARMS] <= 0 && op->body_info[BODY_ARMS])
48 op->body_info[BODY_ARMS]) { 47 {
49 new_draw_info(NDI_UNIQUE, 0,op,"But you have no free hands to steal with!"); 48 new_draw_info (NDI_UNIQUE, 0, op, "But you have no free hands to steal with!");
50 return -1; 49 return -1;
51 } 50 }
52 51
53 /* ADJUSTMENTS */ 52 /* ADJUSTMENTS */
54 53
55 /* Its harder to steal from hostile beings! */ 54 /* Its harder to steal from hostile beings! */
56 if(!QUERY_FLAG(victim, FLAG_UNAGGRESSIVE)) roll = roll/2; 55 if (!QUERY_FLAG (victim, FLAG_UNAGGRESSIVE))
56 roll = roll / 2;
57 57
58 /* Easier to steal from sleeping beings, or if the thief is 58 /* Easier to steal from sleeping beings, or if the thief is
59 * unseen */ 59 * unseen */
60 if(QUERY_FLAG(victim, FLAG_SLEEP)) 60 if (QUERY_FLAG (victim, FLAG_SLEEP))
61 roll = roll*3; 61 roll = roll * 3;
62 else if(op->invisible) 62 else if (op->invisible)
63 roll = roll*2; 63 roll = roll * 2;
64 64
65 /* check stealing 'encumberance'. Having this equipment applied makes 65 /* check stealing 'encumberance'. Having this equipment applied makes
66 * it quite a bit harder to steal. 66 * it quite a bit harder to steal.
67 */ 67 */
68 for(equip=op->inv;equip;equip=equip->below) { 68 for (equip = op->inv; equip; equip = equip->below)
69 {
69 if(equip->type==WEAPON&&QUERY_FLAG(equip,FLAG_APPLIED)) { 70 if (equip->type == WEAPON && QUERY_FLAG (equip, FLAG_APPLIED))
71 {
70 roll -= equip->weight/10000; 72 roll -= equip->weight / 10000;
71 } 73 }
72 if(equip->type==BOW&&QUERY_FLAG(equip,FLAG_APPLIED)) 74 if (equip->type == BOW && QUERY_FLAG (equip, FLAG_APPLIED))
73 roll -= equip->weight/5000; 75 roll -= equip->weight / 5000;
74 if(equip->type==SHIELD&&QUERY_FLAG(equip,FLAG_APPLIED)) { 76 if (equip->type == SHIELD && QUERY_FLAG (equip, FLAG_APPLIED))
77 {
75 roll -= equip->weight/2000; 78 roll -= equip->weight / 2000;
76 } 79 }
77 if(equip->type==ARMOUR&&QUERY_FLAG(equip,FLAG_APPLIED)) 80 if (equip->type == ARMOUR && QUERY_FLAG (equip, FLAG_APPLIED))
78 roll -= equip->weight/5000; 81 roll -= equip->weight / 5000;
79 if(equip->type==GLOVES&&QUERY_FLAG(equip,FLAG_APPLIED)) 82 if (equip->type == GLOVES && QUERY_FLAG (equip, FLAG_APPLIED))
80 roll -= equip->weight/100; 83 roll -= equip->weight / 100;
81 } 84 }
82 if(roll<0) roll=0; 85 if (roll < 0)
86 roll = 0;
83 return roll; 87 return roll;
84} 88}
85 89
86/* 90/*
87 * When stealing: dependent on the intelligence/wisdom of whom you're 91 * When stealing: dependent on the intelligence/wisdom of whom you're
88 * stealing from (op in attempt_steal), offset by your dexterity and 92 * stealing from (op in attempt_steal), offset by your dexterity and
91 * op is the target (person being pilfered) 95 * op is the target (person being pilfered)
92 * who is the person doing the stealing. 96 * who is the person doing the stealing.
93 * skill is the skill object (stealing). 97 * skill is the skill object (stealing).
94 */ 98 */
95 99
100static int
96static int attempt_steal(object* op, object* who, object *skill) 101attempt_steal (object *op, object *who, object *skill)
97{ 102{
98 object *success=NULL, *tmp=NULL, *next; 103 object *success = NULL, *tmp = NULL, *next;
99 int roll=0, chance=0, stats_value; 104 int roll = 0, chance = 0, stats_value;
100 rv_vector rv; 105 rv_vector rv;
101 106
102 stats_value = ((who->stats.Dex + who->stats.Int) * 3) / 2; 107 stats_value = ((who->stats.Dex + who->stats.Int) * 3) / 2;
103 108
104 /* if the victim is aware of a thief in the area (FLAG_NO_STEAL set on them) 109 /* if the victim is aware of a thief in the area (FLAG_NO_STEAL set on them)
105 * they will try to prevent stealing if they can. Only unseen theives will 110 * they will try to prevent stealing if they can. Only unseen theives will
106 * have much chance of success. 111 * have much chance of success.
107 */ 112 */
108 if(op->type!=PLAYER && QUERY_FLAG(op,FLAG_NO_STEAL)) { 113 if (op->type != PLAYER && QUERY_FLAG (op, FLAG_NO_STEAL))
114 {
109 if(can_detect_enemy(op,who,&rv)) { 115 if (can_detect_enemy (op, who, &rv))
116 {
110 npc_call_help(op); 117 npc_call_help (op);
111 CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); 118 CLEAR_FLAG (op, FLAG_UNAGGRESSIVE);
112 new_draw_info(NDI_UNIQUE, 0,who,"Your attempt is prevented!"); 119 new_draw_info (NDI_UNIQUE, 0, who, "Your attempt is prevented!");
120 return 0;
121 }
122 else /* help npc to detect thief next time by raising its wisdom */
123 op->stats.Wis += (op->stats.Int / 5) + 1;
124 if (op->stats.Wis > MAX_STAT)
125 op->stats.Wis = MAX_STAT;
126 }
127 if (op->type == PLAYER && QUERY_FLAG (op, FLAG_WIZ))
128 {
129 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n");
130 return 0;
131 }
132#ifdef PROHIBIT_PLAYERKILL
133 if (op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful))
134 {
135 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
136 return 0;
137 }
138#else
139 if (op->type == PLAYER && who->type == PLAYER && settings.no_player_stealing)
140 {
141 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
142 return 0;
143 }
144#endif
145
146
147 /* Ok then, go thru their inventory, stealing */
148 for (tmp = op->inv; tmp != NULL; tmp = next)
149 {
150 next = tmp->below;
151
152 /* you can't steal worn items, starting items, wiz stuff,
153 * innate abilities, or items w/o a type. Generally
154 * speaking, the invisibility flag prevents experience or
155 * abilities from being stolen since these types are currently
156 * always invisible objects. I was implicit here so as to prevent
157 * future possible problems. -b.t.
158 * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL
159 * already -b.t.
160 */
161
162 if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) || QUERY_FLAG (tmp, FLAG_APPLIED)
163 || !(tmp->type)
164 || tmp->type == EXPERIENCE || tmp->type == SPELL
165 || QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_STEAL) || tmp->invisible)
166 continue;
167
168 /* Okay, try stealing this item. Dependent on dexterity of thief,
169 * skill level, see the adj_stealroll fctn for more detail.
170 */
171
172 roll = die_roll (2, 100, who, PREFER_LOW) / 2; /* weighted 1-100 */
173
174 if ((chance = adj_stealchance (who, op, (stats_value + skill->level * 10 - op->level * 3))) == -1)
175 return 0;
176 else if (roll < chance)
177 {
178 pick_up (who, tmp);
179 /* need to see if the player actually stole this item -
180 * if it is in the players inv, assume it is. This prevents
181 * abuses where the player can not carry the item, so just
182 * keeps stealing it over and over.
183 */
184 if (tmp->destroyed () || tmp->env != op)
185 {
186 /* for players, play_sound: steals item */
187 success = tmp;
188 CLEAR_FLAG (tmp, FLAG_INV_LOCKED);
189
190 /* Don't delete it from target player until we know
191 * the thief has picked it up. can't just look at tmp->count,
192 * as it's possible that it got merged when picked up.
193 */
194 if (op->type == PLAYER)
195 esrv_del_item (op->contr, tmp->count);
196 }
197 break;
198 }
199 } /* for loop looking for an item */
200
201 if (!tmp)
202 {
203 new_draw_info_format (NDI_UNIQUE, 0, who, "%s%s has nothing you can steal!", op->type == PLAYER ? "" : "The ", query_name (op));
204 return 0;
205 }
206
207 /* If you arent high enough level, you might get something BUT
208 * the victim will notice your stealing attempt. Ditto if you
209 * attempt to steal something heavy off them, they're bound to notice
210 */
211
212 if ((roll >= skill->level) || !chance
213 || (tmp && tmp->weight > (250 * (random_roll (0, stats_value + skill->level * 10 - 1, who, PREFER_LOW)))))
214 {
215
216 /* victim figures out where the thief is! */
217 if (who->hide)
218 make_visible (who);
219
220 if (op->type != PLAYER)
221 {
222 /* The unaggressives look after themselves 8) */
223 if (who->type == PLAYER)
224 {
225 npc_call_help (op);
226 new_draw_info_format (NDI_UNIQUE, 0, who, "%s notices your attempted pilfering!", query_name (op));
227 }
228 CLEAR_FLAG (op, FLAG_UNAGGRESSIVE);
229 /* all remaining npc items are guarded now. Set flag NO_STEAL
230 * on the victim.
231 */
232 SET_FLAG (op, FLAG_NO_STEAL);
233 }
234 else
235 { /* stealing from another player */
236 char buf[MAX_BUF];
237
238 /* Notify the other player */
239 if (success && who->stats.Int > random_roll (0, 19, op, PREFER_LOW))
240 {
241 sprintf (buf, "Your %s is missing!", query_name (success));
242 }
243 else
244 {
245 sprintf (buf, "Your pack feels strangely lighter.");
246 }
247 new_draw_info (NDI_UNIQUE, 0, op, buf);
248 if (!success)
249 {
250 if (who->invisible)
251 {
252 sprintf (buf, "you feel itchy fingers getting at your pack.");
253 }
254 else
255 {
256 sprintf (buf, "%s looks very shifty.", query_name (who));
257 }
258 new_draw_info (NDI_UNIQUE, 0, op, buf);
259 }
260 } /* else stealing from another player */
261 /* play_sound("stop! thief!"); kindofthing */
262 } /* if you weren't 100% successful */
263 return success ? 1 : 0;
264}
265
266
267int
268steal (object *op, int dir, object *skill)
269{
270 object *tmp, *next;
271 sint16 x, y;
272 maptile *m;
273 int mflags;
274
275 x = op->x + freearr_x[dir];
276 y = op->y + freearr_y[dir];
277
278 if (dir == 0)
279 {
280 /* Can't steal from ourself! */
281 return 0;
282 }
283
284 m = op->map;
285 mflags = get_map_flags (m, &m, x, y, &x, &y);
286 /* Out of map - can't do it. If nothing alive on this space,
287 * don't need to look any further.
288 */
289 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
290 return 0;
291
292 /* If player can't move onto the space, can't steal from it. */
293 if (OB_TYPE_MOVE_BLOCK (op, GET_MAP_MOVE_BLOCK (m, x, y)))
294 return 0;
295
296 /* Find the topmost object at this spot */
297 for (tmp = get_map_ob (m, x, y); tmp != NULL && tmp->above != NULL; tmp = tmp->above);
298
299 /* For all the stacked objects at this point, attempt a steal */
300 for (; tmp != NULL; tmp = next)
301 {
302 next = tmp->below;
303 /* Minor hack--for multi square beings - make sure we get
304 * the 'head' coz 'tail' objects have no inventory! - b.t.
305 */
306 if (tmp->head)
307 tmp = tmp->head;
308
309 if (tmp->type != PLAYER && !QUERY_FLAG (tmp, FLAG_MONSTER))
310 continue;
311
312 /* do not reveal hidden DMs */
313 if (tmp->type == PLAYER && QUERY_FLAG (tmp, FLAG_WIZ) && tmp->contr->hidden)
314 continue;
315 if (attempt_steal (tmp, op, skill))
316 {
317 if (tmp->type == PLAYER) /* no xp for stealing from another player */
113 return 0; 318 return 0;
114 } else /* help npc to detect thief next time by raising its wisdom */
115 op->stats.Wis += (op->stats.Int/5)+1;
116 if (op->stats.Wis > MAX_STAT) op->stats.Wis = MAX_STAT;
117 }
118 if (op->type == PLAYER && QUERY_FLAG(op, FLAG_WIZ)) {
119 new_draw_info(NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n");
120 return 0;
121 }
122#ifdef PROHIBIT_PLAYERKILL
123 if(op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful)) {
124 new_draw_info(NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
125 return 0;
126 }
127#else
128 if(op->type == PLAYER && who->type == PLAYER && settings.no_player_stealing) {
129 new_draw_info(NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
130 return 0;
131 }
132#endif
133 319
134 320 /* no xp for stealing from pets (of players) */
135 /* Ok then, go thru their inventory, stealing */ 321 if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE)
136 for(tmp = op->inv; tmp != NULL; tmp = next) {
137 next = tmp->below;
138
139 /* you can't steal worn items, starting items, wiz stuff,
140 * innate abilities, or items w/o a type. Generally
141 * speaking, the invisibility flag prevents experience or
142 * abilities from being stolen since these types are currently
143 * always invisible objects. I was implicit here so as to prevent
144 * future possible problems. -b.t.
145 * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL
146 * already -b.t.
147 */ 322 {
323 object *owner = get_owner (tmp);
148 324
149 if (QUERY_FLAG(tmp,FLAG_WAS_WIZ) || QUERY_FLAG(tmp, FLAG_APPLIED) 325 if (owner != NULL && owner->type == PLAYER)
150 || !(tmp->type)
151 || tmp->type == EXPERIENCE || tmp->type == SPELL
152 || QUERY_FLAG(tmp,FLAG_STARTEQUIP)
153 || QUERY_FLAG(tmp,FLAG_NO_STEAL)
154 || tmp->invisible ) continue;
155
156 /* Okay, try stealing this item. Dependent on dexterity of thief,
157 * skill level, see the adj_stealroll fctn for more detail.
158 */
159
160 roll=die_roll(2, 100, who, PREFER_LOW)/2; /* weighted 1-100 */
161
162 if((chance=adj_stealchance(who,op,(stats_value+skill->level * 10 - op->level * 3)))==-1)
163 return 0; 326 return 0;
164 else if (roll < chance ) {
165 tag_t tmp_count = tmp->count;
166
167 pick_up(who, tmp);
168 /* need to see if the player actually stole this item -
169 * if it is in the players inv, assume it is. This prevents
170 * abuses where the player can not carry the item, so just
171 * keeps stealing it over and over.
172 */
173 if (was_destroyed(tmp, tmp_count) || tmp->env != op) {
174 /* for players, play_sound: steals item */
175 success = tmp;
176 CLEAR_FLAG(tmp, FLAG_INV_LOCKED);
177
178 /* Don't delete it from target player until we know
179 * the thief has picked it up. can't just look at tmp->count,
180 * as it's possible that it got merged when picked up.
181 */
182 if (op->type == PLAYER)
183 esrv_del_item(op->contr, tmp_count);
184 } 327 }
185 break;
186 }
187 } /* for loop looking for an item */
188 328
189 if (!tmp) {
190 new_draw_info_format(NDI_UNIQUE, 0, who, "%s%s has nothing you can steal!",
191 op->type == PLAYER ? "" : "The ", query_name(op));
192 return 0;
193 }
194
195 /* If you arent high enough level, you might get something BUT
196 * the victim will notice your stealing attempt. Ditto if you
197 * attempt to steal something heavy off them, they're bound to notice
198 */
199
200 if((roll>=skill->level) || !chance
201 ||(tmp && tmp->weight>(250*(random_roll(0, stats_value+skill->level * 10-1, who, PREFER_LOW))))) {
202
203 /* victim figures out where the thief is! */
204 if(who->hide) make_visible(who);
205
206 if(op->type != PLAYER) {
207 /* The unaggressives look after themselves 8) */
208 if(who->type==PLAYER) {
209 npc_call_help(op);
210 new_draw_info_format(NDI_UNIQUE, 0,who,
211 "%s notices your attempted pilfering!",query_name(op));
212 }
213 CLEAR_FLAG(op, FLAG_UNAGGRESSIVE);
214 /* all remaining npc items are guarded now. Set flag NO_STEAL
215 * on the victim.
216 */
217 SET_FLAG(op,FLAG_NO_STEAL);
218 } else { /* stealing from another player */
219 char buf[MAX_BUF];
220 /* Notify the other player */
221 if (success && who->stats.Int > random_roll(0, 19, op, PREFER_LOW)) {
222 sprintf(buf, "Your %s is missing!", query_name(success));
223 } else {
224 sprintf(buf, "Your pack feels strangely lighter.");
225 }
226 new_draw_info(NDI_UNIQUE, 0,op,buf);
227 if (!success) {
228 if (who->invisible) {
229 sprintf(buf, "you feel itchy fingers getting at your pack.");
230 } else {
231 sprintf(buf, "%s looks very shifty.", query_name(who));
232 }
233 new_draw_info(NDI_UNIQUE, 0,op,buf);
234 }
235 } /* else stealing from another player */
236 /* play_sound("stop! thief!"); kindofthing */
237 } /* if you weren't 100% successful */
238 return success? 1:0;
239}
240
241
242int steal(object* op, int dir, object *skill)
243{
244 object *tmp, *next;
245 sint16 x, y;
246 mapstruct *m;
247 int mflags;
248
249 x = op->x + freearr_x[dir];
250 y = op->y + freearr_y[dir];
251
252 if(dir == 0) {
253 /* Can't steal from ourself! */
254 return 0;
255 }
256
257 m = op->map;
258 mflags = get_map_flags(m, &m ,x,y, &x, &y);
259 /* Out of map - can't do it. If nothing alive on this space,
260 * don't need to look any further.
261 */
262 if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE))
263 return 0;
264
265 /* If player can't move onto the space, can't steal from it. */
266 if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y)))
267 return 0;
268
269 /* Find the topmost object at this spot */
270 for(tmp = get_map_ob(m,x,y);
271 tmp != NULL && tmp->above != NULL;
272 tmp = tmp->above);
273
274 /* For all the stacked objects at this point, attempt a steal */
275 for(; tmp != NULL; tmp = next) {
276 next = tmp->below;
277 /* Minor hack--for multi square beings - make sure we get
278 * the 'head' coz 'tail' objects have no inventory! - b.t.
279 */
280 if (tmp->head) tmp=tmp->head;
281
282 if(tmp->type!=PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) continue;
283
284 /* do not reveal hidden DMs */
285 if (tmp->type == PLAYER && QUERY_FLAG(tmp, FLAG_WIZ) && tmp->contr->hidden) continue;
286 if (attempt_steal(tmp, op, skill)) {
287 if (tmp->type==PLAYER) /* no xp for stealing from another player */
288 return 0;
289
290 /* no xp for stealing from pets (of players) */
291 if (QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE) {
292 object *owner = get_owner(tmp);
293 if (owner != NULL && owner->type == PLAYER)
294 return 0;
295 }
296
297 // reduce monster experience by experience we gained, as to 329 // reduce monster experience by experience we gained, as to
298 // limit the amount of exp that can be gained by stealing from monsters 330 // limit the amount of exp that can be gained by stealing from monsters
299 // (jessies gave ~20,000,000 exp otherwise. 331 // (jessies gave ~20,000,000 exp otherwise.
300 int exp = calc_skill_exp (op, tmp, skill); 332 int exp = calc_skill_exp (op, tmp, skill);
333
301 exp = MIN (tmp->stats.exp, exp); 334 exp = MIN (tmp->stats.exp, exp);
302 tmp->stats.exp -= exp; 335 tmp->stats.exp -= exp;
303 return exp; 336 return exp;
304 } 337 }
305 } 338 }
306 return 0; 339 return 0;
307} 340}
308 341
342static int
309static int attempt_pick_lock (object *door, object *pl, object *skill) 343attempt_pick_lock (object *door, object *pl, object *skill)
310{ 344{
311 int difficulty= pl->map->difficulty ? pl->map->difficulty : 0; 345 int difficulty = pl->map->difficulty ? pl->map->difficulty : 0;
312 int success = 0, number; /* did we get anything? */ 346 int success = 0, number; /* did we get anything? */
313 347
314 348
315 /* Try to pick the lock on this item (doors only for now). 349 /* Try to pick the lock on this item (doors only for now).
316 * Dependent on dexterity/skill SK_level of the player and 350 * Dependent on dexterity/skill SK_level of the player and
317 * the map level difficulty. 351 * the map level difficulty.
318 */ 352 */
319 number = (die_roll(2, 40, pl, PREFER_LOW)-2)/2; 353 number = (die_roll (2, 40, pl, PREFER_LOW) - 2) / 2;
320 if (number < (pl->stats.Dex + skill->level - difficulty)) { 354 if (number < (pl->stats.Dex + skill->level - difficulty))
355 {
321 remove_door(door); 356 remove_door (door);
322 success = 1; 357 success = 1;
323 } else if (door->inv && (door->inv->type==RUNE || door->inv->type==TRAP)) { /* set off any traps? */
324 spring_trap(door->inv,pl);
325 } 358 }
359 else if (door->inv && (door->inv->type == RUNE || door->inv->type == TRAP))
360 { /* set off any traps? */
361 spring_trap (door->inv, pl);
362 }
326 return success; 363 return success;
327} 364}
328 365
329 366
330/* Implementation by bt. (thomas@astro.psu.edu) 367/* Implementation by bt. (thomas@astro.psu.edu)
331 * monster implementation 7-7-95 by bt. 368 * monster implementation 7-7-95 by bt.
332 */ 369 */
333 370
371int
334int pick_lock(object *pl, int dir, object *skill) 372pick_lock (object *pl, int dir, object *skill)
335{ 373{
336 object *tmp; 374 object *tmp;
337 int x = pl->x + freearr_x[dir]; 375 int x = pl->x + freearr_x[dir];
338 int y = pl->y + freearr_y[dir]; 376 int y = pl->y + freearr_y[dir];
339 377
378 if (!dir)
340 if(!dir) dir=pl->facing; 379 dir = pl->facing;
341 380
342 /* For all the stacked objects at this point find a door*/ 381 /* For all the stacked objects at this point find a door */
343 if (out_of_map(pl->map,x,y)) { 382 if (out_of_map (pl->map, x, y))
383 {
344 new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); 384 new_draw_info (NDI_UNIQUE, 0, pl, "There is no lock there.");
345 return 0; 385 return 0;
346 } 386 }
347 387
348 for(tmp=get_map_ob(pl->map,x,y); tmp; tmp=tmp->above) 388 for (tmp = get_map_ob (pl->map, x, y); tmp; tmp = tmp->above)
349 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) break; 389 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR)
390 break;
350 391
351 if (!tmp) { 392 if (!tmp)
393 {
352 new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); 394 new_draw_info (NDI_UNIQUE, 0, pl, "There is no lock there.");
353 return 0; 395 return 0;
354 } 396 }
355 if (tmp->type == LOCKED_DOOR) { 397 if (tmp->type == LOCKED_DOOR)
398 {
356 new_draw_info(NDI_UNIQUE, 0,pl, "You can't pick that lock!"); 399 new_draw_info (NDI_UNIQUE, 0, pl, "You can't pick that lock!");
357 return 0; 400 return 0;
358 } 401 }
359 402
360 if (!tmp->move_block) { 403 if (!tmp->move_block)
404 {
361 new_draw_info(NDI_UNIQUE, 0,pl,"The door has no lock!"); 405 new_draw_info (NDI_UNIQUE, 0, pl, "The door has no lock!");
362 return 0; 406 return 0;
363 } 407 }
364 408
365 if (attempt_pick_lock(tmp, pl, skill)) { 409 if (attempt_pick_lock (tmp, pl, skill))
410 {
366 new_draw_info(NDI_UNIQUE, 0,pl,"You pick the lock."); 411 new_draw_info (NDI_UNIQUE, 0, pl, "You pick the lock.");
367 return calc_skill_exp(pl,NULL, skill); 412 return calc_skill_exp (pl, NULL, skill);
368 } else { 413 }
414 else
415 {
369 new_draw_info(NDI_UNIQUE, 0,pl, "You fail to pick the lock."); 416 new_draw_info (NDI_UNIQUE, 0, pl, "You fail to pick the lock.");
370 return 0; 417 return 0;
371 } 418 }
372} 419}
373 420
374 421
375/* HIDE CODE. The user becomes undetectable (not just 'invisible') for 422/* HIDE CODE. The user becomes undetectable (not just 'invisible') for
376 * a short while (success and duration dependant on player SK_level, 423 * a short while (success and duration dependant on player SK_level,
377 * dexterity, charisma, and map difficulty). 424 * dexterity, charisma, and map difficulty).
378 * Players have a good chance of becoming 'unhidden' if they move 425 * Players have a good chance of becoming 'unhidden' if they move
379 * and like invisiblity will be come visible if they attack 426 * and like invisiblity will be come visible if they attack
380 * Implemented by b.t. (thomas@astro.psu.edu) 427 * Implemented by b.t. (thomas@astro.psu.edu)
381 * July 7, 1995 - made hiding possible for monsters. -b.t. 428 * July 7, 1995 - made hiding possible for monsters. -b.t.
382 */ 429 */
383 430
431static int
384static int attempt_hide(object *op, object *skill) { 432attempt_hide (object *op, object *skill)
433{
385 int number,difficulty=op->map->difficulty; 434 int number, difficulty = op->map->difficulty;
386 int terrain = hideability(op); 435 int terrain = hideability (op);
387 436
388 if(terrain<-10) /* not enough cover here */ 437 if (terrain < -10) /* not enough cover here */
389 return 0;
390
391 /* Hiding success and duration dependant on skill level,
392 * op->stats.Dex, map difficulty and terrain.
393 */
394
395 number = (die_roll(2, 25, op, PREFER_LOW)-2)/2;
396 if(!stand_near_hostile(op) && (number < (op->stats.Dex + skill->level + terrain - difficulty))) {
397 op->invisible += 100; /* set the level of 'hiddeness' */
398 if(op->type==PLAYER)
399 op->contr->tmp_invis=1;
400 op->hide=1;
401 return 1;
402 }
403 return 0; 438 return 0;
439
440 /* Hiding success and duration dependant on skill level,
441 * op->stats.Dex, map difficulty and terrain.
442 */
443
444 number = (die_roll (2, 25, op, PREFER_LOW) - 2) / 2;
445 if (!stand_near_hostile (op) && (number < (op->stats.Dex + skill->level + terrain - difficulty)))
446 {
447 op->invisible += 100; /* set the level of 'hiddeness' */
448 if (op->type == PLAYER)
449 op->contr->tmp_invis = 1;
450 op->hide = 1;
451 return 1;
452 }
453 return 0;
404} 454}
405 455
406/* patched this to take terrain into consideration */ 456/* patched this to take terrain into consideration */
407 457int
408int hide(object *op, object *skill) { 458hide (object *op, object *skill)
459{
409 460
410 /* the preliminaries -- Can we really hide now? */ 461 /* the preliminaries -- Can we really hide now? */
411 /* this keeps monsters from using invisibilty spells and hiding */ 462 /* this keeps monsters from using invisibilty spells and hiding */
412 463
413 if (QUERY_FLAG(op, FLAG_MAKE_INVIS)) { 464 if (QUERY_FLAG (op, FLAG_MAKE_INVIS))
465 {
414 new_draw_info(NDI_UNIQUE, 0,op,"You don't need to hide while invisible!"); 466 new_draw_info (NDI_UNIQUE, 0, op, "You don't need to hide while invisible!");
415 return 0; 467 return 0;
468 }
416 } else if (!op->hide && op->invisible>0 && op->type == PLAYER) { 469 else if (!op->hide && op->invisible > 0 && op->type == PLAYER)
470 {
417 new_draw_info(NDI_UNIQUE, 0,op,"Your attempt to hide breaks the invisibility spell!"); 471 new_draw_info (NDI_UNIQUE, 0, op, "Your attempt to hide breaks the invisibility spell!");
418 make_visible(op); 472 make_visible (op);
419 } 473 }
420 474
421 if(op->invisible>(50*skill->level)) { 475 if (op->invisible > (50 * skill->level))
476 {
422 new_draw_info(NDI_UNIQUE,0,op,"You are as hidden as you can get."); 477 new_draw_info (NDI_UNIQUE, 0, op, "You are as hidden as you can get.");
423 return 0; 478 return 0;
424 } 479 }
425 480
426 if(attempt_hide(op, skill)) { 481 if (attempt_hide (op, skill))
482 {
427 new_draw_info(NDI_UNIQUE, 0,op,"You hide in the shadows."); 483 new_draw_info (NDI_UNIQUE, 0, op, "You hide in the shadows.");
428 update_object(op,UP_OBJ_FACE); 484 update_object (op, UP_OBJ_FACE);
429 return calc_skill_exp(op, NULL, skill); 485 return calc_skill_exp (op, NULL, skill);
430 } 486 }
431 new_draw_info(NDI_UNIQUE,0,op,"You fail to conceal yourself."); 487 new_draw_info (NDI_UNIQUE, 0, op, "You fail to conceal yourself.");
432 return 0; 488 return 0;
433} 489}
434 490
435 491
436/* stop_jump() - End of jump. Clear flags, restore the map, and 492/* stop_jump() - End of jump. Clear flags, restore the map, and
437 * freeze the jumper a while to simulate the exhaustion 493 * freeze the jumper a while to simulate the exhaustion
438 * of jumping. 494 * of jumping.
439 */ 495 */
496static void
440static void stop_jump(object *pl, int dist, int spaces) { 497stop_jump (object *pl, int dist, int spaces)
498{
441 fix_player(pl); 499 fix_player (pl);
442 insert_ob_in_map(pl,pl->map,pl,0); 500 insert_ob_in_map (pl, pl->map, pl, 0);
443} 501}
444 502
445 503
504static int
446static int attempt_jump (object *pl, int dir, int spaces, object *skill) { 505attempt_jump (object *pl, int dir, int spaces, object *skill)
506{
447 object *tmp; 507 object *tmp;
448 int i,exp=0,dx=freearr_x[dir],dy=freearr_y[dir], mflags; 508 int i, exp = 0, dx = freearr_x[dir], dy = freearr_y[dir], mflags;
449 sint16 x, y; 509 sint16 x, y;
450 mapstruct *m; 510 maptile *m;
451 511
452 /* Jump loop. Go through spaces opject wants to jump. Halt the 512 /* Jump loop. Go through spaces opject wants to jump. Halt the
453 * jump if a wall or creature is in the way. We set FLAG_FLYING 513 * jump if a wall or creature is in the way. We set FLAG_FLYING
454 * temporarily to allow player to aviod exits/archs that are not 514 * temporarily to allow player to aviod exits/archs that are not
455 * fly_on, fly_off. This will also prevent pickup of objects 515 * fly_on, fly_off. This will also prevent pickup of objects
456 * while jumping over them. 516 * while jumping over them.
457 */ 517 */
458 518
459 remove_ob(pl); 519 remove_ob (pl);
460 520
461 /* 521 /*
462 * I don't think this is actually needed - all the movement 522 * I don't think this is actually needed - all the movement
463 * code is handled in this function, and I don't see anyplace 523 * code is handled in this function, and I don't see anyplace
464 * that cares about the move_type being flying. 524 * that cares about the move_type being flying.
465 */ 525 */
466 pl->move_type |= MOVE_FLY_LOW; 526 pl->move_type |= MOVE_FLY_LOW;
467 527
468 for(i=0;i<=spaces;i++) { 528 for (i = 0; i <= spaces; i++)
529 {
469 x = pl->x + dx; 530 x = pl->x + dx;
470 y = pl->y + dy; 531 y = pl->y + dy;
471 m = pl->map; 532 m = pl->map;
472 533
473 mflags = get_map_flags(m, &m, x, y, &x, &y); 534 mflags = get_map_flags (m, &m, x, y, &x, &y);
474 535
475 if (mflags & P_OUT_OF_MAP) { 536 if (mflags & P_OUT_OF_MAP)
537 {
476 (void) stop_jump(pl,i,spaces); 538 (void) stop_jump (pl, i, spaces);
477 return 0; 539 return 0;
478 } 540 }
479 if (OB_TYPE_MOVE_BLOCK(pl, GET_MAP_MOVE_BLOCK(m, x, y))) { 541 if (OB_TYPE_MOVE_BLOCK (pl, GET_MAP_MOVE_BLOCK (m, x, y)))
542 {
480 new_draw_info(NDI_UNIQUE, 0,pl,"Your jump is blocked."); 543 new_draw_info (NDI_UNIQUE, 0, pl, "Your jump is blocked.");
481 stop_jump(pl,i,spaces); 544 stop_jump (pl, i, spaces);
482 return 0; 545 return 0;
483 } 546 }
484 547
485 for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { 548 for (tmp = get_map_ob (m, x, y); tmp; tmp = tmp->above)
549 {
486 /* Jump into creature */ 550 /* Jump into creature */
487 if(QUERY_FLAG(tmp, FLAG_MONSTER)
488 || (tmp->type==PLAYER && (!QUERY_FLAG(tmp, FLAG_WIZ) || !tmp->contr->hidden))) { 551 if (QUERY_FLAG (tmp, FLAG_MONSTER) || (tmp->type == PLAYER && (!QUERY_FLAG (tmp, FLAG_WIZ) || !tmp->contr->hidden)))
489 new_draw_info_format(NDI_UNIQUE, 0,pl,"You jump into %s%s.", 552 {
490 tmp->type == PLAYER ? "" : "the ", &tmp->name); 553 new_draw_info_format (NDI_UNIQUE, 0, pl, "You jump into %s%s.", tmp->type == PLAYER ? "" : "the ", &tmp->name);
491 if(tmp->type!=PLAYER || 554 if (tmp->type != PLAYER ||
492 (pl->type==PLAYER && pl->contr->party==NULL) || 555 (pl->type == PLAYER && pl->contr->party == NULL) ||
493 (pl->type==PLAYER && tmp->type==PLAYER && 556 (pl->type == PLAYER && tmp->type == PLAYER && pl->contr->party != tmp->contr->party))
494 pl->contr->party!=tmp->contr->party))
495 exp = skill_attack(tmp,pl,pl->facing,"kicked", skill); /* pl makes an attack */ 557 exp = skill_attack (tmp, pl, pl->facing, "kicked", skill); /* pl makes an attack */
496 stop_jump(pl,i,spaces); 558 stop_jump (pl, i, spaces);
497 return exp; /* note that calc_skill_exp() is already called by skill_attack() */ 559 return exp; /* note that calc_skill_exp() is already called by skill_attack() */
498 } 560 }
499 /* If the space has fly on set (no matter what the space is), 561 /* If the space has fly on set (no matter what the space is),
500 * we should get the effects - after all, the player is 562 * we should get the effects - after all, the player is
501 * effectively flying. 563 * effectively flying.
502 */ 564 */
503 if (tmp->move_on & MOVE_FLY_LOW) { 565 if (tmp->move_on & MOVE_FLY_LOW)
566 {
504 pl->x = x; 567 pl->x = x;
505 pl->y = y; 568 pl->y = y;
506 pl->map = m; 569 pl->map = m;
507 stop_jump(pl,i,spaces); 570 stop_jump (pl, i, spaces);
508 return calc_skill_exp(pl,NULL, skill); 571 return calc_skill_exp (pl, NULL, skill);
509 } 572 }
510 } 573 }
511 pl->x = x; 574 pl->x = x;
512 pl->y = y; 575 pl->y = y;
513 pl->map = m; 576 pl->map = m;
514 } 577 }
515 stop_jump(pl,i,spaces); 578 stop_jump (pl, i, spaces);
516 return calc_skill_exp(pl,NULL, skill); 579 return calc_skill_exp (pl, NULL, skill);
517} 580}
518 581
519/* jump() - this is both a new type of movement for player/monsters and 582/* jump() - this is both a new type of movement for player/monsters and
520 * an attack as well. 583 * an attack as well.
521 * Perhaps we should allow more spaces based on level, eg, level 50 584 * Perhaps we should allow more spaces based on level, eg, level 50
522 * jumper can jump several spaces? 585 * jumper can jump several spaces?
523 */ 586 */
524 587
588int
525int jump(object *pl, int dir, object *skill) 589jump (object *pl, int dir, object *skill)
526{ 590{
527 int spaces=0,stats; 591 int spaces = 0, stats;
528 int str = pl->stats.Str; 592 int str = pl->stats.Str;
529 int dex = pl->stats.Dex; 593 int dex = pl->stats.Dex;
530 594
531 dex = dex ? dex : 15; 595 dex = dex ? dex : 15;
532 str = str ? str : 10; 596 str = str ? str : 10;
533 597
534 stats=str*str*str*dex * skill->level; 598 stats = str * str * str * dex * skill->level;
535 599
536 if(pl->carrying!=0) /* don't want div by zero !! */ 600 if (pl->carrying != 0) /* don't want div by zero !! */
537 spaces=(int) (stats/pl->carrying); 601 spaces = (int) (stats / pl->carrying);
538 else 602 else
539 spaces=2; /* pl has no objects - gets the far jump */ 603 spaces = 2; /* pl has no objects - gets the far jump */
540 604
541 if(spaces>2) 605 if (spaces > 2)
542 spaces = 2; 606 spaces = 2;
543 else if(spaces==0) { 607 else if (spaces == 0)
608 {
544 new_draw_info(NDI_UNIQUE, 0,pl,"You are carrying too much weight to jump."); 609 new_draw_info (NDI_UNIQUE, 0, pl, "You are carrying too much weight to jump.");
545 return 0; 610 return 0;
546 } 611 }
547 return attempt_jump(pl,dir,spaces, skill); 612 return attempt_jump (pl, dir, spaces, skill);
548} 613}
549 614
550 615
551/* skill_ident() - this code is supposed to allow players to identify 616/* skill_ident() - this code is supposed to allow players to identify
552 * classes of objects with the various "auto-ident" skills. Player must 617 * classes of objects with the various "auto-ident" skills. Player must
556 * more generalized. Right now, skill indices are embedded in this routine. 621 * more generalized. Right now, skill indices are embedded in this routine.
557 * Returns amount of experience gained (on successful ident). 622 * Returns amount of experience gained (on successful ident).
558 * - b.t. (thomas@astro.psu.edu) 623 * - b.t. (thomas@astro.psu.edu)
559 */ 624 */
560 625
626static int
561static int do_skill_detect_curse(object *pl, object *skill) { 627do_skill_detect_curse (object *pl, object *skill)
628{
562 object *tmp; 629 object *tmp;
563 int success=0; 630 int success = 0;
564 631
565 for(tmp=pl->inv;tmp;tmp=tmp->below) 632 for (tmp = pl->inv; tmp; tmp = tmp->below)
566 if (!tmp->invisible 633 if (!tmp->invisible
567 && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) 634 && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED)
568 && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && 635 && (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) && tmp->item_power < skill->level)
569 tmp->item_power < skill->level) { 636 {
570 SET_FLAG(tmp,FLAG_KNOWN_CURSED); 637 SET_FLAG (tmp, FLAG_KNOWN_CURSED);
571 esrv_update_item(UPD_FLAGS, pl, tmp); 638 esrv_update_item (UPD_FLAGS, pl, tmp);
572 success+= calc_skill_exp(pl,tmp, skill); 639 success += calc_skill_exp (pl, tmp, skill);
573 } 640 }
574 641
575 /* Check ground, too, but only objects the player could pick up */ 642 /* Check ground, too, but only objects the player could pick up */
576 for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) 643 for (tmp = get_map_ob (pl->map, pl->x, pl->y); tmp; tmp = tmp->above)
577 if (can_pick(pl, tmp) && 644 if (can_pick (pl, tmp) &&
578 !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && 645 !QUERY_FLAG (tmp, FLAG_IDENTIFIED) &&
579 !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) 646 !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED)
580 && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && 647 && (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED)) && tmp->item_power < skill->level)
581 tmp->item_power < skill->level) { 648 {
582 SET_FLAG(tmp,FLAG_KNOWN_CURSED); 649 SET_FLAG (tmp, FLAG_KNOWN_CURSED);
583 esrv_update_item(UPD_FLAGS, pl, tmp); 650 esrv_update_item (UPD_FLAGS, pl, tmp);
584 success+= calc_skill_exp(pl,tmp, skill); 651 success += calc_skill_exp (pl, tmp, skill);
585 } 652 }
586 653
587 return success; 654 return success;
588} 655}
589 656
657static int
590static int do_skill_detect_magic(object *pl, object *skill) { 658do_skill_detect_magic (object *pl, object *skill)
659{
591 object *tmp; 660 object *tmp;
592 int success=0; 661 int success = 0;
593 662
594 for(tmp=pl->inv;tmp;tmp=tmp->below) 663 for (tmp = pl->inv; tmp; tmp = tmp->below)
595 if(!tmp->invisible 664 if (!tmp->invisible
596 && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) 665 && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL)
597 && (is_magical(tmp)) && tmp->item_power < skill->level) { 666 && (is_magical (tmp)) && tmp->item_power < skill->level)
667 {
598 SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); 668 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
599 esrv_update_item(UPD_FLAGS, pl, tmp); 669 esrv_update_item (UPD_FLAGS, pl, tmp);
600 success+=calc_skill_exp(pl,tmp, skill); 670 success += calc_skill_exp (pl, tmp, skill);
601 } 671 }
602 672
603 /* Check ground, too, but like above, only if the object can be picked up*/ 673 /* Check ground, too, but like above, only if the object can be picked up */
604 for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) 674 for (tmp = get_map_ob (pl->map, pl->x, pl->y); tmp; tmp = tmp->above)
605 if (can_pick(pl, tmp) && 675 if (can_pick (pl, tmp) &&
606 !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && 676 !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && (is_magical (tmp)) && tmp->item_power < skill->level)
607 !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) 677 {
608 && (is_magical(tmp)) && tmp->item_power < skill->level) {
609 SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); 678 SET_FLAG (tmp, FLAG_KNOWN_MAGICAL);
610 esrv_update_item(UPD_FLAGS, pl, tmp); 679 esrv_update_item (UPD_FLAGS, pl, tmp);
611 success+=calc_skill_exp(pl,tmp, skill); 680 success += calc_skill_exp (pl, tmp, skill);
612 } 681 }
613 682
614 return success; 683 return success;
615} 684}
616 685
617/* Helper function for do_skill_ident, so that we can loop 686/* Helper function for do_skill_ident, so that we can loop
618 * over inventory AND objects on the ground conveniently. 687 * over inventory AND objects on the ground conveniently.
619 */ 688 */
689int
620int do_skill_ident2(object *tmp,object *pl, int obj_class, object *skill) 690do_skill_ident2 (object *tmp, object *pl, int obj_class, object *skill)
621{ 691{
622 int success = 0, chance; 692 int success = 0, chance;
623 int skill_value = skill->level * pl->stats.Int ? pl->stats.Int : 10; 693 int skill_value = skill->level * pl->stats.Int ? pl->stats.Int : 10;
624 694
625 if (!QUERY_FLAG (tmp,FLAG_IDENTIFIED) && !QUERY_FLAG (tmp,FLAG_NO_SKILL_IDENT) 695 if (!QUERY_FLAG (tmp, FLAG_IDENTIFIED) && !QUERY_FLAG (tmp, FLAG_NO_SKILL_IDENT)
626 && need_identify (tmp) && !tmp->invisible && tmp->type == obj_class) 696 && need_identify (tmp) && !tmp->invisible && tmp->type == obj_class)
627 { 697 {
628 chance = die_roll(3, 10, pl, PREFER_LOW) - 3 698 chance = die_roll (3, 10, pl, PREFER_LOW) - 3 + rndm (0, (tmp->magic ? tmp->magic * 5 : 1) - 1);
629 + rndm (0, (tmp->magic ? tmp->magic * 5 : 1) - 1);
630 699
631 if (skill_value >= chance) 700 if (skill_value >= chance)
632 { 701 {
633 identify(tmp); 702 identify (tmp);
634 703
635 if (pl->type==PLAYER) 704 if (pl->type == PLAYER)
636 { 705 {
637 new_draw_info_format (NDI_UNIQUE, 0, pl, "You identify %s.", long_desc (tmp, pl)); 706 new_draw_info_format (NDI_UNIQUE, 0, pl, "You identify %s.", long_desc (tmp, pl));
638 707
639 if (tmp->msg) 708 if (tmp->msg)
640 { 709 {
641 new_draw_info(NDI_UNIQUE, 0,pl, "The item has a story:"); 710 new_draw_info (NDI_UNIQUE, 0, pl, "The item has a story:");
642 new_draw_info(NDI_UNIQUE, 0,pl, tmp->msg); 711 new_draw_info (NDI_UNIQUE, 0, pl, tmp->msg);
643 } 712 }
644 713
645 /* identify will take care of updating the item if it is in the players inventory. IF on map, do it here */ 714 /* identify will take care of updating the item if it is in the players inventory. IF on map, do it here */
646 if (tmp->map) 715 if (tmp->map)
647 esrv_send_item (pl, tmp); 716 esrv_send_item (pl, tmp);
648 } 717 }
649 success += calc_skill_exp(pl,tmp, skill); 718 success += calc_skill_exp (pl, tmp, skill);
650 } 719 }
651 else 720 else
652 SET_FLAG (tmp, FLAG_NO_SKILL_IDENT); 721 SET_FLAG (tmp, FLAG_NO_SKILL_IDENT);
653 } 722 }
654 723
655 return success; 724 return success;
656} 725}
657 726
658/* do_skill_ident() - workhorse for skill_ident() -b.t. 727/* do_skill_ident() - workhorse for skill_ident() -b.t.
659 */ 728 */
729static int
660static int do_skill_ident(object *pl, int obj_class, object *skill) { 730do_skill_ident (object *pl, int obj_class, object *skill)
731{
661 object *tmp; 732 object *tmp;
662 int success=0; 733 int success = 0;
663 734
664 for(tmp=pl->inv;tmp;tmp=tmp->below) 735 for (tmp = pl->inv; tmp; tmp = tmp->below)
665 success+=do_skill_ident2(tmp,pl,obj_class, skill); 736 success += do_skill_ident2 (tmp, pl, obj_class, skill);
666 /* check the ground */ 737 /* check the ground */
667 738
668 for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) 739 for (tmp = get_map_ob (pl->map, pl->x, pl->y); tmp; tmp = tmp->above)
669 success+=do_skill_ident2(tmp,pl,obj_class, skill); 740 success += do_skill_ident2 (tmp, pl, obj_class, skill);
670 741
671 return success; 742 return success;
672} 743}
673 744
745int
674int skill_ident(object *pl, object *skill) { 746skill_ident (object *pl, object *skill)
747{
675 int success=0; 748 int success = 0;
676 749
677 if(pl->type != PLAYER) return 0; /* only players will skill-identify */ 750 if (pl->type != PLAYER)
751 return 0; /* only players will skill-identify */
678 752
679 new_draw_info(NDI_UNIQUE, 0,pl,"You look at the objects nearby..."); 753 new_draw_info (NDI_UNIQUE, 0, pl, "You look at the objects nearby...");
680 754
681 switch (skill->subtype) { 755 switch (skill->subtype)
756 {
682 case SK_SMITHERY: 757 case SK_SMITHERY:
683 success += do_skill_ident(pl,WEAPON, skill) + do_skill_ident(pl,ARMOUR, skill) 758 success += do_skill_ident (pl, WEAPON, skill) + do_skill_ident (pl, ARMOUR, skill)
684 + do_skill_ident(pl,BRACERS,skill) + do_skill_ident(pl,CLOAK,skill) 759 + do_skill_ident (pl, BRACERS, skill) + do_skill_ident (pl, CLOAK, skill)
685 + do_skill_ident(pl,BOOTS,skill) + do_skill_ident(pl,SHIELD,skill) 760 + do_skill_ident (pl, BOOTS, skill) + do_skill_ident (pl, SHIELD, skill)
686 + do_skill_ident(pl,GIRDLE,skill) + do_skill_ident(pl,HELMET,skill) 761 + do_skill_ident (pl, GIRDLE, skill) + do_skill_ident (pl, HELMET, skill) + do_skill_ident (pl, GLOVES, skill);
687 + do_skill_ident(pl,GLOVES,skill);
688 break; 762 break;
689 763
690 case SK_BOWYER: 764 case SK_BOWYER:
691 success += do_skill_ident(pl,BOW,skill) + do_skill_ident(pl,ARROW,skill); 765 success += do_skill_ident (pl, BOW, skill) + do_skill_ident (pl, ARROW, skill);
692 break; 766 break;
693 767
694 case SK_ALCHEMY: 768 case SK_ALCHEMY:
695 success += do_skill_ident(pl,POTION,skill) + do_skill_ident(pl,POISON,skill) 769 success += do_skill_ident (pl, POTION, skill) + do_skill_ident (pl, POISON, skill)
696 + do_skill_ident(pl,CONTAINER,skill) 770 + do_skill_ident (pl, CONTAINER, skill) + do_skill_ident (pl, DRINK, skill) + do_skill_ident (pl, INORGANIC, skill);
697 + do_skill_ident(pl,DRINK,skill) + do_skill_ident(pl,INORGANIC,skill);
698 break; 771 break;
699 772
700 case SK_WOODSMAN: 773 case SK_WOODSMAN:
701 success += do_skill_ident(pl,FOOD,skill) + do_skill_ident(pl,DRINK,skill) 774 success += do_skill_ident (pl, FOOD, skill) + do_skill_ident (pl, DRINK, skill) + do_skill_ident (pl, FLESH, skill);
702 + do_skill_ident(pl,FLESH,skill);
703 break; 775 break;
704 776
705 case SK_JEWELER: 777 case SK_JEWELER:
706 success += do_skill_ident(pl,GEM,skill) + do_skill_ident(pl,RING,skill) + 778 success += do_skill_ident (pl, GEM, skill) + do_skill_ident (pl, RING, skill) + do_skill_ident (pl, AMULET, skill);
707 do_skill_ident(pl,AMULET,skill);
708 break; 779 break;
709 780
710 case SK_LITERACY: 781 case SK_LITERACY:
711 success += do_skill_ident(pl,SPELLBOOK,skill) 782 success += do_skill_ident (pl, SPELLBOOK, skill) + do_skill_ident (pl, SCROLL, skill) + do_skill_ident (pl, BOOK, skill);
712 + do_skill_ident(pl,SCROLL,skill) + do_skill_ident(pl,BOOK,skill);
713 break; 783 break;
714 784
715 case SK_THAUMATURGY: 785 case SK_THAUMATURGY:
716 success += do_skill_ident(pl,WAND,skill) + do_skill_ident(pl,ROD,skill) 786 success += do_skill_ident (pl, WAND, skill) + do_skill_ident (pl, ROD, skill) + do_skill_ident (pl, HORN, skill);
717 + do_skill_ident(pl,HORN,skill);
718 break; 787 break;
719 788
720 case SK_DET_CURSE: 789 case SK_DET_CURSE:
721 success = do_skill_detect_curse(pl,skill); 790 success = do_skill_detect_curse (pl, skill);
722 if(success) 791 if (success)
723 new_draw_info(NDI_UNIQUE, 0,pl,"...and discover cursed items!"); 792 new_draw_info (NDI_UNIQUE, 0, pl, "...and discover cursed items!");
724 break; 793 break;
725 794
726 case SK_DET_MAGIC: 795 case SK_DET_MAGIC:
727 success = do_skill_detect_magic(pl,skill); 796 success = do_skill_detect_magic (pl, skill);
728 if(success) 797 if (success)
729 new_draw_info(NDI_UNIQUE, 0,pl,
730 "...and discover items imbued with mystic forces!"); 798 new_draw_info (NDI_UNIQUE, 0, pl, "...and discover items imbued with mystic forces!");
731 break; 799 break;
732 800
733 default: 801 default:
734 LOG(llevError,"Error: bad call to skill_ident()\n"); 802 LOG (llevError, "Error: bad call to skill_ident()\n");
735 return 0; 803 return 0;
736 break; 804 break;
737 } 805 }
738 if(!success) { 806 if (!success)
807 {
739 new_draw_info(NDI_UNIQUE, 0,pl,"...and learn nothing more."); 808 new_draw_info (NDI_UNIQUE, 0, pl, "...and learn nothing more.");
740 } 809 }
741 return success; 810 return success;
742} 811}
743 812
744 813
745/* players using this skill can 'charm' a monster -- 814/* players using this skill can 'charm' a monster --
746 * into working for them. It can only be used on 815 * into working for them. It can only be used on
747 * non-special (see below) 'neutral' creatures. 816 * non-special (see below) 'neutral' creatures.
748 * -b.t. (thomas@astro.psu.edu) 817 * -b.t. (thomas@astro.psu.edu)
749 */ 818 */
750 819
820int
751int use_oratory(object *pl, int dir, object *skill) { 821use_oratory (object *pl, int dir, object *skill)
822{
752 sint16 x=pl->x+freearr_x[dir],y=pl->y+freearr_y[dir]; 823 sint16 x = pl->x + freearr_x[dir], y = pl->y + freearr_y[dir];
753 int mflags,chance; 824 int mflags, chance;
754 object *tmp; 825 object *tmp;
755 mapstruct *m; 826 maptile *m;
756 827
757 if(pl->type!=PLAYER) return 0; /* only players use this skill */ 828 if (pl->type != PLAYER)
829 return 0; /* only players use this skill */
758 m = pl->map; 830 m = pl->map;
759 mflags =get_map_flags(m, &m, x,y, &x, &y); 831 mflags = get_map_flags (m, &m, x, y, &x, &y);
760 if (mflags & P_OUT_OF_MAP) return 0; 832 if (mflags & P_OUT_OF_MAP)
833 return 0;
761 834
762 /* Save some processing - we have the flag already anyways 835 /* Save some processing - we have the flag already anyways
763 */ 836 */
764 if (!(mflags & P_IS_ALIVE)) { 837 if (!(mflags & P_IS_ALIVE))
838 {
765 new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to."); 839 new_draw_info (NDI_UNIQUE, 0, pl, "There is nothing to orate to.");
840 return 0;
841 }
842
843 for (tmp = get_map_ob (m, x, y); tmp; tmp = tmp->above)
844 {
845 /* can't persuade players - return because there is nothing else
846 * on that space to charm. Same for multi space monsters and
847 * special monsters - we don't allow them to be charmed, and there
848 * is no reason to do further processing since they should be the
849 * only monster on the space.
850 */
851 if (tmp->type == PLAYER)
766 return 0; 852 return 0;
767 }
768
769 for(tmp=get_map_ob(m,x,y);tmp;tmp=tmp->above) {
770 /* can't persuade players - return because there is nothing else
771 * on that space to charm. Same for multi space monsters and
772 * special monsters - we don't allow them to be charmed, and there
773 * is no reason to do further processing since they should be the
774 * only monster on the space.
775 */
776 if(tmp->type==PLAYER) return 0;
777 if(tmp->more || tmp->head) return 0; 853 if (tmp->more || tmp->head)
778 if(tmp->msg) return 0;
779
780 if(QUERY_FLAG(tmp,FLAG_MONSTER)) break;
781 }
782
783 if (!tmp) {
784 new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to.");
785 return 0; 854 return 0;
855 if (tmp->msg)
856 return 0;
857
858 if (QUERY_FLAG (tmp, FLAG_MONSTER))
859 break;
860 }
861
862 if (!tmp)
786 } 863 {
864 new_draw_info (NDI_UNIQUE, 0, pl, "There is nothing to orate to.");
865 return 0;
866 }
787 867
788 new_draw_info_format(NDI_UNIQUE, 868 new_draw_info_format (NDI_UNIQUE, 0, pl, "You orate to the %s.", query_name (tmp));
789 0,pl, "You orate to the %s.",query_name(tmp));
790 869
791 /* the following conditions limit who may be 'charmed' */ 870 /* the following conditions limit who may be 'charmed' */
792 871
793 /* it's hostile! */ 872 /* it's hostile! */
794 if(!QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && !QUERY_FLAG(tmp, FLAG_FRIENDLY)) { 873 if (!QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && !QUERY_FLAG (tmp, FLAG_FRIENDLY))
795 new_draw_info_format(NDI_UNIQUE, 0,pl, 874 {
796 "Too bad the %s isn't listening!\n",query_name(tmp)); 875 new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp));
797 return 0; 876 return 0;
798 } 877 }
799 878
800 /* it's already allied! */ 879 /* it's already allied! */
801 if(QUERY_FLAG(tmp,FLAG_FRIENDLY)&&(tmp->attack_movement==PETMOVE)){ 880 if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && (tmp->attack_movement == PETMOVE))
881 {
802 if(get_owner(tmp)==pl) { 882 if (get_owner (tmp) == pl)
803 new_draw_info(NDI_UNIQUE, 0,pl, 883 {
804 "Your follower loves your speech.\n"); 884 new_draw_info (NDI_UNIQUE, 0, pl, "Your follower loves your speech.\n");
805 return 0; 885 return 0;
886 }
806 } else if (skill->level > tmp->level) { 887 else if (skill->level > tmp->level)
888 {
807 /* you steal the follower. Perhaps we should really look at the 889 /* you steal the follower. Perhaps we should really look at the
808 * level of the owner above? 890 * level of the owner above?
809 */ 891 */
810 set_owner(tmp,pl); 892 set_owner (tmp, pl);
811 new_draw_info_format(NDI_UNIQUE, 0,pl, 893 new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to follow you instead!\n", query_name (tmp));
812 "You convince the %s to follow you instead!\n",
813 query_name(tmp));
814 /* Abuse fix - don't give exp since this can otherwise 894 /* Abuse fix - don't give exp since this can otherwise
815 * be used by a couple players to gets lots of exp. 895 * be used by a couple players to gets lots of exp.
816 */ 896 */
817 return 0; 897 return 0;
898 }
818 } else { 899 else
900 {
819 /* In this case, you can't steal it from the other player */ 901 /* In this case, you can't steal it from the other player */
820 return 0; 902 return 0;
821 } 903 }
822 } /* Creature was already a pet of someone */ 904 } /* Creature was already a pet of someone */
823 905
824 chance=skill->level*2+(pl->stats.Cha-2*tmp->stats.Int)/2; 906 chance = skill->level * 2 + (pl->stats.Cha - 2 * tmp->stats.Int) / 2;
825 907
826 /* Ok, got a 'sucker' lets try to make them a follower */ 908 /* Ok, got a 'sucker' lets try to make them a follower */
827 if(chance>0 && tmp->level<(random_roll(0, chance-1, pl, PREFER_HIGH)-1)) { 909 if (chance > 0 && tmp->level < (random_roll (0, chance - 1, pl, PREFER_HIGH) - 1))
828 new_draw_info_format(NDI_UNIQUE, 0,pl, 910 {
829 "You convince the %s to become your follower.\n", 911 new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to become your follower.\n", query_name (tmp));
830 query_name(tmp));
831 912
832 set_owner(tmp,pl); 913 set_owner (tmp, pl);
833 tmp->stats.exp = 0; 914 tmp->stats.exp = 0;
834 add_friendly_object(tmp); 915 add_friendly_object (tmp);
835 SET_FLAG(tmp,FLAG_FRIENDLY); 916 SET_FLAG (tmp, FLAG_FRIENDLY);
836 tmp->attack_movement = PETMOVE; 917 tmp->attack_movement = PETMOVE;
837 return calc_skill_exp(pl,tmp, skill); 918 return calc_skill_exp (pl, tmp, skill);
838 } 919 }
839 /* Charm failed. Creature may be angry now */ 920 /* Charm failed. Creature may be angry now */
840 else if((skill->level+((pl->stats.Cha-10)/2)) < random_roll(1, 2*tmp->level, pl, PREFER_LOW)) { 921 else if ((skill->level + ((pl->stats.Cha - 10) / 2)) < random_roll (1, 2 * tmp->level, pl, PREFER_LOW))
841 new_draw_info_format(NDI_UNIQUE, 0,pl, 922 {
842 "Your speech angers the %s!\n",query_name(tmp)); 923 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your speech angers the %s!\n", query_name (tmp));
843 if(QUERY_FLAG(tmp,FLAG_FRIENDLY)) { 924 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
925 {
844 CLEAR_FLAG(tmp,FLAG_FRIENDLY); 926 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
845 remove_friendly_object(tmp); 927 remove_friendly_object (tmp);
846 tmp->attack_movement = 0; /* needed? */ 928 tmp->attack_movement = 0; /* needed? */
847 } 929 }
848 CLEAR_FLAG(tmp,FLAG_UNAGGRESSIVE); 930 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
849 } 931 }
850 return 0; /* Fall through - if we get here, we didn't charm anything */ 932 return 0; /* Fall through - if we get here, we didn't charm anything */
851} 933}
852 934
853/* Singing() -this skill allows the player to pacify nearby creatures. 935/* Singing() -this skill allows the player to pacify nearby creatures.
854 * There are few limitations on who/what kind of 936 * There are few limitations on who/what kind of
855 * non-player creatures that may be pacified. Right now, a player 937 * non-player creatures that may be pacified. Right now, a player
858 * may only pacify a creature once. 940 * may only pacify a creature once.
859 * BTW, I appologize for the naming of the skill, I couldnt think 941 * BTW, I appologize for the naming of the skill, I couldnt think
860 * of anything better! -b.t. 942 * of anything better! -b.t.
861 */ 943 */
862 944
945int
863int singing(object *pl, int dir, object *skill) { 946singing (object *pl, int dir, object *skill)
947{
864 int i,exp = 0,chance, mflags; 948 int i, exp = 0, chance, mflags;
865 object *tmp; 949 object *tmp;
866 mapstruct *m; 950 maptile *m;
867 sint16 x, y; 951 sint16 x, y;
868 952
869 if(pl->type!=PLAYER) return 0; /* only players use this skill */ 953 if (pl->type != PLAYER)
954 return 0; /* only players use this skill */
870 955
871 new_draw_info_format(NDI_UNIQUE,0,pl, "You sing."); 956 new_draw_info_format (NDI_UNIQUE, 0, pl, "You sing.");
872 for(i=0;i<MIN(skill->level,SIZEOFFREE);i++) { 957 for (i = 0; i < MIN (skill->level, SIZEOFFREE); i++)
958 {
873 x = pl->x+freearr_x[i]; 959 x = pl->x + freearr_x[i];
874 y = pl->y+freearr_y[i]; 960 y = pl->y + freearr_y[i];
875 m = pl->map; 961 m = pl->map;
876 962
877 mflags =get_map_flags(m, &m, x,y, &x, &y); 963 mflags = get_map_flags (m, &m, x, y, &x, &y);
878 if (mflags & P_OUT_OF_MAP) continue; 964 if (mflags & P_OUT_OF_MAP)
965 continue;
879 if (!(mflags & P_IS_ALIVE)) continue; 966 if (!(mflags & P_IS_ALIVE))
967 continue;
880 968
881 for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { 969 for (tmp = get_map_ob (m, x, y); tmp; tmp = tmp->above)
970 {
882 if(QUERY_FLAG(tmp,FLAG_MONSTER)) break; 971 if (QUERY_FLAG (tmp, FLAG_MONSTER))
972 break;
883 /* can't affect players */ 973 /* can't affect players */
884 if(tmp->type==PLAYER) break; 974 if (tmp->type == PLAYER)
975 break;
885 } 976 }
886 977
887 /* Whole bunch of checks to see if this is a type of monster that would 978 /* Whole bunch of checks to see if this is a type of monster that would
888 * listen to singing. 979 * listen to singing.
889 */ 980 */
890 if (tmp && QUERY_FLAG(tmp, FLAG_MONSTER) && 981 if (tmp && QUERY_FLAG (tmp, FLAG_MONSTER) && !QUERY_FLAG (tmp, FLAG_NO_STEAL) && /* Been charmed or abused before */
891 !QUERY_FLAG(tmp, FLAG_NO_STEAL) && /* Been charmed or abused before */
892 !QUERY_FLAG(tmp, FLAG_SPLITTING) && /* no ears */ 982 !QUERY_FLAG (tmp, FLAG_SPLITTING) && /* no ears */
893 !QUERY_FLAG(tmp, FLAG_HITBACK) && /* was here before */ 983 !QUERY_FLAG (tmp, FLAG_HITBACK) && /* was here before */
894 (tmp->level <= skill->level) && 984 (tmp->level <= skill->level) && (!tmp->head) && !QUERY_FLAG (tmp, FLAG_UNDEAD) && !QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE) && /* already calm */
895 (!tmp->head) &&
896 !QUERY_FLAG(tmp, FLAG_UNDEAD) && 985 !QUERY_FLAG (tmp, FLAG_FRIENDLY))
897 !QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && /* already calm */ 986 { /* already calm */
898 !QUERY_FLAG(tmp,FLAG_FRIENDLY)) { /* already calm */
899 987
900 /* stealing isn't really related (although, maybe it should 988 /* stealing isn't really related (although, maybe it should
901 * be). This is mainly to prevent singing to the same monster 989 * be). This is mainly to prevent singing to the same monster
902 * over and over again and getting exp for it. 990 * over and over again and getting exp for it.
903 */ 991 */
904 chance=skill->level*2+(pl->stats.Cha-5-tmp->stats.Int)/2; 992 chance = skill->level * 2 + (pl->stats.Cha - 5 - tmp->stats.Int) / 2;
905 if(chance && tmp->level*2<random_roll(0, chance-1, pl, PREFER_HIGH)) { 993 if (chance && tmp->level * 2 < random_roll (0, chance - 1, pl, PREFER_HIGH))
994 {
906 SET_FLAG(tmp,FLAG_UNAGGRESSIVE); 995 SET_FLAG (tmp, FLAG_UNAGGRESSIVE);
907 new_draw_info_format(NDI_UNIQUE, 0,pl, 996 new_draw_info_format (NDI_UNIQUE, 0, pl, "You calm down the %s\n", query_name (tmp));
908 "You calm down the %s\n",query_name(tmp));
909 /* Give exp only if they are not aware */ 997 /* Give exp only if they are not aware */
910 if(!QUERY_FLAG(tmp,FLAG_NO_STEAL)) 998 if (!QUERY_FLAG (tmp, FLAG_NO_STEAL))
911 exp += calc_skill_exp(pl,tmp, skill); 999 exp += calc_skill_exp (pl, tmp, skill);
912 SET_FLAG(tmp,FLAG_NO_STEAL); 1000 SET_FLAG (tmp, FLAG_NO_STEAL);
913 } else {
914 new_draw_info_format(NDI_UNIQUE, 0,pl,
915 "Too bad the %s isn't listening!\n",query_name(tmp));
916 SET_FLAG(tmp,FLAG_NO_STEAL);
917 } 1001 }
1002 else
1003 {
1004 new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp));
1005 SET_FLAG (tmp, FLAG_NO_STEAL);
918 } 1006 }
1007 }
919 } 1008 }
920 return exp; 1009 return exp;
921} 1010}
922 1011
923/* The find_traps skill (aka, search). Checks for traps 1012/* The find_traps skill (aka, search). Checks for traps
924 * on the spaces or in certain objects 1013 * on the spaces or in certain objects
925 */ 1014 */
926 1015
1016int
927int find_traps (object *pl, object *skill) { 1017find_traps (object *pl, object *skill)
1018{
928 object *tmp,*tmp2; 1019 object *tmp, *tmp2;
929 int i,expsum=0, mflags; 1020 int i, expsum = 0, mflags;
930 sint16 x,y; 1021 sint16 x, y;
931 mapstruct *m; 1022 maptile *m;
932 1023
933 /* First we search all around us for runes and traps, which are 1024 /* First we search all around us for runes and traps, which are
934 * all type RUNE 1025 * all type RUNE
935 */ 1026 */
936 1027
937 for(i=0;i<9;i++) { 1028 for (i = 0; i < 9; i++)
1029 {
938 x = pl->x+freearr_x[i]; 1030 x = pl->x + freearr_x[i];
939 y = pl->y+freearr_y[i]; 1031 y = pl->y + freearr_y[i];
940 m = pl->map; 1032 m = pl->map;
941 1033
942 mflags =get_map_flags(m, &m, x,y, &x, &y); 1034 mflags = get_map_flags (m, &m, x, y, &x, &y);
943 if (mflags & P_OUT_OF_MAP) continue; 1035 if (mflags & P_OUT_OF_MAP)
1036 continue;
944 1037
945 /* Check everything in the square for trapness */ 1038 /* Check everything in the square for trapness */
946 for(tmp = get_map_ob(m, x, y); tmp!=NULL;tmp=tmp->above) { 1039 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
1040 {
947 1041
948 /* And now we'd better do an inventory traversal of each 1042 /* And now we'd better do an inventory traversal of each
949 * of these objects' inventory 1043 * of these objects' inventory
950 * We can narrow this down a bit - no reason to search through 1044 * We can narrow this down a bit - no reason to search through
951 * the players inventory or monsters for that matter. 1045 * the players inventory or monsters for that matter.
952 */ 1046 */
953 if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) { 1047 if (tmp->type != PLAYER && !QUERY_FLAG (tmp, FLAG_MONSTER))
1048 {
954 for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) 1049 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
955 if(tmp2->type==RUNE || tmp2->type == TRAP) 1050 if (tmp2->type == RUNE || tmp2->type == TRAP)
956 if(trap_see(pl,tmp2)) { 1051 if (trap_see (pl, tmp2))
1052 {
957 trap_show(tmp2,tmp); 1053 trap_show (tmp2, tmp);
958 if(tmp2->stats.Cha>1) { 1054 if (tmp2->stats.Cha > 1)
959 if (!tmp2->owner || tmp2->owner->type!=PLAYER)
960 expsum += calc_skill_exp(pl,tmp2, skill);
961
962 tmp2->stats.Cha = 1; /* unhide the trap */
963 }
964 } 1055 {
965 }
966 if((tmp->type==RUNE || tmp->type == TRAP) && trap_see(pl,tmp)) {
967 trap_show(tmp,tmp);
968 if(tmp->stats.Cha>1) {
969 if (!tmp->owner || tmp->owner->type!=PLAYER) 1056 if (!tmp2->owner || tmp2->owner->type != PLAYER)
970 expsum += calc_skill_exp(pl,tmp, skill); 1057 expsum += calc_skill_exp (pl, tmp2, skill);
1058
971 tmp->stats.Cha = 1; /* unhide the trap */ 1059 tmp2->stats.Cha = 1; /* unhide the trap */
972 }
973 }
974 }
975 }
976 new_draw_info(NDI_BLACK, 0, pl, "You search the area.");
977 return expsum;
978}
979
980/* remove_trap() - This skill will disarm any previously discovered trap
981 * the algorithm is based (almost totally) on the old command_disarm() - b.t.
982 */
983
984int remove_trap (object *op, int dir, object *skill) {
985 object *tmp,*tmp2;
986 int i,success=0,mflags;
987 mapstruct *m;
988 sint16 x,y;
989
990 for(i=0;i<9;i++) {
991 x = op->x + freearr_x[i];
992 y = op->y + freearr_y[i];
993 m = op->map;
994
995 mflags =get_map_flags(m, &m, x,y, &x, &y);
996 if (mflags & P_OUT_OF_MAP) continue;
997
998 /* Check everything in the square for trapness */
999 for(tmp = get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above) {
1000 /* And now we'd better do an inventory traversal of each
1001 * of these objects inventory. Like above, only
1002 * do this for interesting objects.
1003 */
1004
1005 if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) {
1006 for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below)
1007 if((tmp2->type==RUNE || tmp2->type == TRAP) && tmp2->stats.Cha<=1) {
1008 trap_show(tmp2,tmp);
1009 if(trap_disarm(op,tmp2,1, skill) && (!tmp2->owner || tmp2->owner->type!=PLAYER)) {
1010 tmp->stats.exp = tmp->stats.Cha * tmp->level;
1011 success += calc_skill_exp(op,tmp2, skill);
1012 } 1060 }
1013 } 1061 }
1014 } 1062 }
1015 if((tmp->type==RUNE || tmp->type==TRAP) && tmp->stats.Cha<=1) { 1063 if ((tmp->type == RUNE || tmp->type == TRAP) && trap_see (pl, tmp))
1064 {
1016 trap_show(tmp,tmp); 1065 trap_show (tmp, tmp);
1066 if (tmp->stats.Cha > 1)
1067 {
1017 if (trap_disarm(op,tmp,1,skill) && (!tmp->owner || tmp->owner->type!=PLAYER)) { 1068 if (!tmp->owner || tmp->owner->type != PLAYER)
1018 tmp->stats.exp = tmp->stats.Cha * tmp->level;
1019 success += calc_skill_exp(op,tmp,skill); 1069 expsum += calc_skill_exp (pl, tmp, skill);
1070 tmp->stats.Cha = 1; /* unhide the trap */
1020 } 1071 }
1021 } 1072 }
1022 } 1073 }
1023 } 1074 }
1075 new_draw_info (NDI_BLACK, 0, pl, "You search the area.");
1076 return expsum;
1077}
1078
1079/* remove_trap() - This skill will disarm any previously discovered trap
1080 * the algorithm is based (almost totally) on the old command_disarm() - b.t.
1081 */
1082
1083int
1084remove_trap (object *op, int dir, object *skill)
1085{
1086 object *tmp, *tmp2;
1087 int i, success = 0, mflags;
1088 maptile *m;
1089 sint16 x, y;
1090
1091 for (i = 0; i < 9; i++)
1092 {
1093 x = op->x + freearr_x[i];
1094 y = op->y + freearr_y[i];
1095 m = op->map;
1096
1097 mflags = get_map_flags (m, &m, x, y, &x, &y);
1098 if (mflags & P_OUT_OF_MAP)
1099 continue;
1100
1101 /* Check everything in the square for trapness */
1102 for (tmp = get_map_ob (m, x, y); tmp != NULL; tmp = tmp->above)
1103 {
1104 /* And now we'd better do an inventory traversal of each
1105 * of these objects inventory. Like above, only
1106 * do this for interesting objects.
1107 */
1108
1109 if (tmp->type != PLAYER && !QUERY_FLAG (tmp, FLAG_MONSTER))
1110 {
1111 for (tmp2 = tmp->inv; tmp2 != NULL; tmp2 = tmp2->below)
1112 if ((tmp2->type == RUNE || tmp2->type == TRAP) && tmp2->stats.Cha <= 1)
1113 {
1114 trap_show (tmp2, tmp);
1115 if (trap_disarm (op, tmp2, 1, skill) && (!tmp2->owner || tmp2->owner->type != PLAYER))
1116 {
1117 tmp->stats.exp = tmp->stats.Cha * tmp->level;
1118 success += calc_skill_exp (op, tmp2, skill);
1119 }
1120 }
1121 }
1122 if ((tmp->type == RUNE || tmp->type == TRAP) && tmp->stats.Cha <= 1)
1123 {
1124 trap_show (tmp, tmp);
1125 if (trap_disarm (op, tmp, 1, skill) && (!tmp->owner || tmp->owner->type != PLAYER))
1126 {
1127 tmp->stats.exp = tmp->stats.Cha * tmp->level;
1128 success += calc_skill_exp (op, tmp, skill);
1129 }
1130 }
1131 }
1132 }
1024 return success; 1133 return success;
1025} 1134}
1026 1135
1027 1136
1028/* pray() - when this skill is called from do_skill(), it allows 1137/* pray() - when this skill is called from do_skill(), it allows
1029 * the player to regain lost grace points at a faster rate. -b.t. 1138 * the player to regain lost grace points at a faster rate. -b.t.
1031 * such that if it returns true, player gets exp in that skill. This 1140 * such that if it returns true, player gets exp in that skill. This
1032 * the effect here can be done on demand, we probably don't want to 1141 * the effect here can be done on demand, we probably don't want to
1033 * give infinite exp by returning true in any cases. 1142 * give infinite exp by returning true in any cases.
1034 */ 1143 */
1035 1144
1145int
1036int pray (object *pl, object *skill) { 1146pray (object *pl, object *skill)
1147{
1037 char buf[MAX_BUF]; 1148 char buf[MAX_BUF];
1038 object *tmp; 1149 object *tmp;
1039 1150
1040 if(pl->type!=PLAYER) return 0; 1151 if (pl->type != PLAYER)
1041
1042 strcpy(buf,"You pray.");
1043
1044 /* Check all objects - we could stop at floor objects,
1045 * but if someone buries an altar, I don't see a problem with
1046 * going through all the objects, and it shouldn't be much slower
1047 * than extra checks on object attributes.
1048 */
1049 for (tmp=pl->below; tmp!=NULL; tmp=tmp->below) {
1050 /* Only if the altar actually belongs to someone do you get special benefits */
1051 if(tmp && tmp->type==HOLY_ALTAR && tmp->other_arch) {
1052 sprintf(buf,"You pray over the %s.", &tmp->name);
1053 pray_at_altar(pl,tmp, skill);
1054 break; /* Only pray at one altar */
1055 }
1056 }
1057
1058 new_draw_info(NDI_BLACK,0,pl,buf);
1059
1060 if(pl->stats.grace < pl->stats.maxgrace) {
1061 pl->stats.grace++;
1062 pl->last_grace = -1;
1063 }
1064 return 0; 1152 return 0;
1153
1154 strcpy (buf, "You pray.");
1155
1156 /* Check all objects - we could stop at floor objects,
1157 * but if someone buries an altar, I don't see a problem with
1158 * going through all the objects, and it shouldn't be much slower
1159 * than extra checks on object attributes.
1160 */
1161 for (tmp = pl->below; tmp != NULL; tmp = tmp->below)
1162 {
1163 /* Only if the altar actually belongs to someone do you get special benefits */
1164 if (tmp && tmp->type == HOLY_ALTAR && tmp->other_arch)
1165 {
1166 sprintf (buf, "You pray over the %s.", &tmp->name);
1167 pray_at_altar (pl, tmp, skill);
1168 break; /* Only pray at one altar */
1169 }
1170 }
1171
1172 new_draw_info (NDI_BLACK, 0, pl, buf);
1173
1174 if (pl->stats.grace < pl->stats.maxgrace)
1175 {
1176 pl->stats.grace++;
1177 pl->last_grace = -1;
1178 }
1179 return 0;
1065} 1180}
1066 1181
1067/* This skill allows the player to regain a few sp or hp for a 1182/* This skill allows the player to regain a few sp or hp for a
1068 * brief period of concentration. No armour or weapons may be 1183 * brief period of concentration. No armour or weapons may be
1069 * wielded/applied for this to work. The amount of time needed 1184 * wielded/applied for this to work. The amount of time needed
1070 * to concentrate and the # of points regained is dependant on 1185 * to concentrate and the # of points regained is dependant on
1071 * the level of the user. - b.t. thomas@astro.psu.edu 1186 * the level of the user. - b.t. thomas@astro.psu.edu
1072 */ 1187 */
1073 1188
1189void
1074void meditate (object *pl, object *skill) { 1190meditate (object *pl, object *skill)
1191{
1075 object *tmp; 1192 object *tmp;
1076 1193
1077 if(pl->type!=PLAYER) return; /* players only */ 1194 if (pl->type != PLAYER)
1195 return; /* players only */
1078 1196
1079 /* check if pl has removed encumbering armour and weapons */ 1197 /* check if pl has removed encumbering armour and weapons */
1080 if(QUERY_FLAG(pl,FLAG_READY_WEAPON) && (skill->level<6)) { 1198 if (QUERY_FLAG (pl, FLAG_READY_WEAPON) && (skill->level < 6))
1081 new_draw_info(NDI_UNIQUE,0,pl, 1199 {
1082 "You can't concentrate while wielding a weapon!\n"); 1200 new_draw_info (NDI_UNIQUE, 0, pl, "You can't concentrate while wielding a weapon!\n");
1083 return; 1201 return;
1084 } else { 1202 }
1203 else
1204 {
1085 for(tmp=pl->inv;tmp;tmp=tmp->below) 1205 for (tmp = pl->inv; tmp; tmp = tmp->below)
1086 if (( (tmp->type==ARMOUR && skill->level<12) 1206 if (((tmp->type == ARMOUR && skill->level < 12)
1087 || (tmp->type==HELMET && skill->level<10) 1207 || (tmp->type == HELMET && skill->level < 10)
1088 || (tmp->type==SHIELD && skill->level<6) 1208 || (tmp->type == SHIELD && skill->level < 6)
1089 || (tmp->type==BOOTS && skill->level<4) 1209 || (tmp->type == BOOTS && skill->level < 4) || (tmp->type == GLOVES && skill->level < 2)) && QUERY_FLAG (tmp, FLAG_APPLIED))
1090 || (tmp->type==GLOVES && skill->level<2) ) 1210 {
1091 && QUERY_FLAG(tmp,FLAG_APPLIED)) {
1092 new_draw_info(NDI_UNIQUE,0,pl,
1093 "You can't concentrate while wearing so much armour!\n"); 1211 new_draw_info (NDI_UNIQUE, 0, pl, "You can't concentrate while wearing so much armour!\n");
1094 return; 1212 return;
1095 } 1213 }
1096 } 1214 }
1097 1215
1098 /* ok let's meditate! Spell points are regained first, then once 1216 /* ok let's meditate! Spell points are regained first, then once
1099 * they are maxed we get back hp. Actual incrementing of values 1217 * they are maxed we get back hp. Actual incrementing of values
1100 * is handled by the do_some_living() (in player.c). This way magical 1218 * is handled by the do_some_living() (in player.c). This way magical
1101 * bonuses for healing/sp regeneration are included properly 1219 * bonuses for healing/sp regeneration are included properly
1102 * No matter what, we will eat up some playing time trying to 1220 * No matter what, we will eat up some playing time trying to
1103 * meditate. (see 'factor' variable for what sets the amount of time) 1221 * meditate. (see 'factor' variable for what sets the amount of time)
1104 */ 1222 */
1105 1223
1106 new_draw_info(NDI_BLACK,0,pl, "You meditate."); 1224 new_draw_info (NDI_BLACK, 0, pl, "You meditate.");
1107 1225
1108 if(pl->stats.sp < pl->stats.maxsp) { 1226 if (pl->stats.sp < pl->stats.maxsp)
1227 {
1109 pl->stats.sp++; 1228 pl->stats.sp++;
1110 pl->last_sp = -1; 1229 pl->last_sp = -1;
1230 }
1111 } else if (pl->stats.hp < pl->stats.maxhp) { 1231 else if (pl->stats.hp < pl->stats.maxhp)
1232 {
1112 pl->stats.hp++; 1233 pl->stats.hp++;
1113 pl->last_heal = -1; 1234 pl->last_heal = -1;
1114 } 1235 }
1115} 1236}
1116 1237
1117/* write_note() - this routine allows players to inscribe messages in 1238/* write_note() - this routine allows players to inscribe messages in
1118 * ordinary 'books' (anything that is type BOOK). b.t. 1239 * ordinary 'books' (anything that is type BOOK). b.t.
1119 */ 1240 */
1120 1241
1242static int
1121static int write_note(object *pl, object *item, const char *msg, object *skill) { 1243write_note (object *pl, object *item, const char *msg, object *skill)
1244{
1122 char buf[1024]; 1245 char buf[1024];
1123 object *newBook = NULL; 1246 object *newBook = NULL;
1124 1247
1125 /* a pair of sanity checks */ 1248 /* a pair of sanity checks */
1126 if(!item||item->type!=BOOK) return 0; 1249 if (!item || item->type != BOOK)
1250 return 0;
1127 1251
1128 if(!msg) { 1252 if (!msg)
1253 {
1129 new_draw_info(NDI_UNIQUE,0,pl,"No message to write!"); 1254 new_draw_info (NDI_UNIQUE, 0, pl, "No message to write!");
1130 new_draw_info_format(NDI_UNIQUE,0,pl,"Usage: use_skill %s <message>", &skill->skill); 1255 new_draw_info_format (NDI_UNIQUE, 0, pl, "Usage: use_skill %s <message>", &skill->skill);
1131 return 0; 1256 return 0;
1132 } 1257 }
1133 if (strcasestr_local(msg, "endmsg")) { 1258 if (strcasestr_local (msg, "endmsg"))
1259 {
1134 new_draw_info(NDI_UNIQUE,0,pl,"Trying to cheat now are we?"); 1260 new_draw_info (NDI_UNIQUE, 0, pl, "Trying to cheat now are we?");
1135 return 0; 1261 return 0;
1136 } 1262 }
1137 1263
1138 if (INVOKE_OBJECT (INSCRIBE_NOTE, item, ARG_PLAYER (pl->contr), ARG_STRING (msg), ARG_OBJECT (skill))) 1264 if (INVOKE_OBJECT (INSCRIBE_NOTE, item, ARG_PLAYER (pl->contr), ARG_STRING (msg), ARG_OBJECT (skill)))
1265 return strlen (msg);
1266
1267 buf[0] = 0;
1268 if (!book_overflow (item->msg, msg, sizeof (buf)))
1269 { /* add msg string to book */
1270 if (item->msg)
1271 strcpy (buf, item->msg);
1272
1273 strcat (buf, msg);
1274 strcat (buf, "\n"); /* new msg needs a LF */
1275 if (item->nrof > 1)
1276 {
1277 newBook = get_object ();
1278 copy_object (item, newBook);
1279 decrease_ob (item);
1280 esrv_send_item (pl, item);
1281 newBook->nrof = 1;
1282 newBook->msg = buf;
1283 newBook = insert_ob_in_ob (newBook, pl);
1284 esrv_send_item (pl, newBook);
1285 }
1286 else
1287 {
1288 item->msg = buf;
1289 /* This shouldn't be necessary - the object hasn't changed in any
1290 * visible way
1291 */
1292 /* esrv_send_item(pl, item); */
1293 }
1294 new_draw_info_format (NDI_UNIQUE, 0, pl, "You write in the %s.", query_short_name (item));
1139 return strlen (msg); 1295 return strlen (msg);
1140 1296 }
1141 buf[0] = 0;
1142 if(!book_overflow(item->msg,msg,sizeof (buf))) { /* add msg string to book */
1143 if(item->msg)
1144 strcpy(buf,item->msg);
1145
1146 strcat(buf,msg);
1147 strcat(buf,"\n"); /* new msg needs a LF */
1148 if(item->nrof > 1) {
1149 newBook = get_object();
1150 copy_object(item, newBook);
1151 decrease_ob(item);
1152 esrv_send_item(pl, item);
1153 newBook->nrof = 1;
1154 newBook->msg = buf;
1155 newBook = insert_ob_in_ob(newBook, pl);
1156 esrv_send_item(pl, newBook);
1157 } else {
1158 item->msg=buf;
1159 /* This shouldn't be necessary - the object hasn't changed in any
1160 * visible way
1161 */
1162 /* esrv_send_item(pl, item);*/
1163 }
1164 new_draw_info_format(NDI_UNIQUE,0,pl, "You write in the %s.",
1165 query_short_name(item));
1166 return strlen(msg);
1167 } else 1297 else
1168 new_draw_info_format(NDI_UNIQUE,0,pl, 1298 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your message won't fit in the %s!", query_short_name (item));
1169 "Your message won't fit in the %s!",
1170 query_short_name(item));
1171 1299
1172 return 0; 1300 return 0;
1173} 1301}
1174 1302
1175/* write_scroll() - this routine allows players to inscribe spell scrolls 1303/* write_scroll() - this routine allows players to inscribe spell scrolls
1176 * of spells which they know. Backfire effects are possible with the 1304 * of spells which they know. Backfire effects are possible with the
1177 * severity of the backlash correlated with the difficulty of the scroll 1305 * severity of the backlash correlated with the difficulty of the scroll
1178 * that is attempted. -b.t. thomas@astro.psu.edu 1306 * that is attempted. -b.t. thomas@astro.psu.edu
1179 */ 1307 */
1180 1308
1309static int
1181static int write_scroll (object *pl, object *scroll, object *skill) { 1310write_scroll (object *pl, object *scroll, object *skill)
1311{
1182 int success=0,confused=0; 1312 int success = 0, confused = 0;
1183 object *newscroll, *chosen_spell, *tmp; 1313 object *newscroll, *chosen_spell, *tmp;
1184 1314
1185 /* this is a sanity check */ 1315 /* this is a sanity check */
1186 if (scroll->type!=SCROLL) { 1316 if (scroll->type != SCROLL)
1317 {
1187 new_draw_info(NDI_UNIQUE,0,pl,"A spell can only be inscribed into a scroll!"); 1318 new_draw_info (NDI_UNIQUE, 0, pl, "A spell can only be inscribed into a scroll!");
1188 return 0; 1319 return 0;
1189 } 1320 }
1190 1321
1191 /* Check if we are ready to attempt inscription */ 1322 /* Check if we are ready to attempt inscription */
1192 chosen_spell=pl->contr->ranges[range_magic]; 1323 chosen_spell = pl->contr->ranges[range_magic];
1193 if(!chosen_spell) { 1324 if (!chosen_spell)
1194 new_draw_info(NDI_UNIQUE,0,pl, 1325 {
1195 "You need a spell readied in order to inscribe!"); 1326 new_draw_info (NDI_UNIQUE, 0, pl, "You need a spell readied in order to inscribe!");
1196 return 0; 1327 return 0;
1197 } 1328 }
1198 if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE) > pl->stats.grace) { 1329 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_GRACE) > pl->stats.grace)
1199 new_draw_info_format(NDI_UNIQUE,0,pl, 1330 {
1200 "You don't have enough grace to write a scroll of %s.", 1331 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough grace to write a scroll of %s.", &chosen_spell->name);
1201 &chosen_spell->name);
1202 return 0; 1332 return 0;
1203 } 1333 }
1204 if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA) > pl->stats.sp) { 1334 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_MANA) > pl->stats.sp)
1205 new_draw_info_format(NDI_UNIQUE,0,pl, 1335 {
1206 "You don't have enough mana to write a scroll of %s.", 1336 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough mana to write a scroll of %s.", &chosen_spell->name);
1207 &chosen_spell->name);
1208 return 0; 1337 return 0;
1209 } 1338 }
1210 1339
1211 /* if there is a spell already on the scroll then player could easily 1340 /* if there is a spell already on the scroll then player could easily
1212 * accidently read it while trying to write the new one. give player 1341 * accidently read it while trying to write the new one. give player
1213 * a 50% chance to overwrite spell at their own level 1342 * a 50% chance to overwrite spell at their own level
1214 */ 1343 */
1215 if((scroll->stats.sp || scroll->inv) && 1344 if ((scroll->stats.sp || scroll->inv) && random_roll (0, scroll->level * 2, pl, PREFER_LOW) > skill->level)
1216 random_roll(0, scroll->level*2, pl, PREFER_LOW)>skill->level) { 1345 {
1217 new_draw_info_format(NDI_UNIQUE,0,pl, 1346 new_draw_info_format (NDI_UNIQUE, 0, pl, "Oops! You accidently read it while trying to write on it.");
1218 "Oops! You accidently read it while trying to write on it.");
1219 manual_apply(pl,scroll,0); 1347 manual_apply (pl, scroll, 0);
1348 return 0;
1349 }
1350
1351 /* ok, we are ready to try inscription */
1352 if (QUERY_FLAG (pl, FLAG_CONFUSED))
1353 confused = 1;
1354
1355 /* Lost mana/grace no matter what */
1356 pl->stats.grace -= SP_level_spellpoint_cost (pl, chosen_spell, SPELL_GRACE);
1357 pl->stats.sp -= SP_level_spellpoint_cost (pl, chosen_spell, SPELL_MANA);
1358
1359 if (random_roll (0, chosen_spell->level * 4 - 1, pl, PREFER_LOW) < skill->level)
1360 {
1361 if (scroll->nrof > 1)
1362 {
1363 newscroll = get_object ();
1364 copy_object (scroll, newscroll);
1365 decrease_ob (scroll);
1366 newscroll->nrof = 1;
1367 }
1368 else
1369 {
1370 newscroll = scroll;
1371 }
1372
1373 if (!confused)
1374 {
1375 newscroll->level = MAX (skill->level, chosen_spell->level);
1376 new_draw_info (NDI_UNIQUE, 0, pl, "You succeed in writing a new scroll.");
1377 }
1378 else
1379 {
1380 chosen_spell = find_random_spell_in_ob (pl, NULL);
1381 if (!chosen_spell)
1220 return 0; 1382 return 0;
1221 }
1222 1383
1223 /* ok, we are ready to try inscription */
1224 if(QUERY_FLAG(pl,FLAG_CONFUSED)) confused = 1;
1225
1226 /* Lost mana/grace no matter what */
1227 pl->stats.grace-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE);
1228 pl->stats.sp-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA);
1229
1230 if (random_roll(0, chosen_spell->level*4-1, pl, PREFER_LOW) < skill->level) {
1231 if (scroll->nrof > 1) {
1232 newscroll = get_object();
1233 copy_object(scroll, newscroll);
1234 decrease_ob(scroll);
1235 newscroll->nrof = 1;
1236 } else {
1237 newscroll = scroll;
1238 }
1239
1240 if(!confused) {
1241 newscroll->level= MAX(skill->level, chosen_spell->level); 1384 newscroll->level = MAX (skill->level, chosen_spell->level);
1242 new_draw_info(NDI_UNIQUE,0,pl,
1243 "You succeed in writing a new scroll.");
1244 } else {
1245 chosen_spell = find_random_spell_in_ob(pl, NULL);
1246 if (!chosen_spell) return 0;
1247
1248 newscroll->level= MAX(skill->level, chosen_spell->level);
1249 new_draw_info(NDI_UNIQUE,0,pl,
1250 "In your confused state, you write down some odd spell."); 1385 new_draw_info (NDI_UNIQUE, 0, pl, "In your confused state, you write down some odd spell.");
1251 } 1386 }
1252 1387
1253 if (newscroll->inv) { 1388 if (newscroll->inv)
1389 {
1254 object *ninv; 1390 object *ninv;
1255 1391
1256 ninv = newscroll->inv; 1392 ninv = newscroll->inv;
1257 remove_ob(ninv); 1393 remove_ob (ninv);
1258 free_object(ninv); 1394 free_object (ninv);
1259 } 1395 }
1260 tmp = get_object(); 1396 tmp = get_object ();
1261 copy_object(chosen_spell, tmp); 1397 copy_object (chosen_spell, tmp);
1262 insert_ob_in_ob(tmp, newscroll); 1398 insert_ob_in_ob (tmp, newscroll);
1263 1399
1264 /* Same code as from treasure.c - so they can better merge. 1400 /* Same code as from treasure.c - so they can better merge.
1265 * if players want to sell them, so be it. 1401 * if players want to sell them, so be it.
1266 */ 1402 */
1267 newscroll->value = newscroll->arch->clone.value * newscroll->inv->value * 1403 newscroll->value = newscroll->arch->clone.value * newscroll->inv->value * (newscroll->level + 50) / (newscroll->inv->level + 50);
1268 (newscroll->level +50) / (newscroll->inv->level + 50);
1269 newscroll->stats.exp = newscroll->value/5; 1404 newscroll->stats.exp = newscroll->value / 5;
1270 1405
1271 /* wait until finished manipulating the scroll before inserting it */ 1406 /* wait until finished manipulating the scroll before inserting it */
1272 if (newscroll == scroll) 1407 if (newscroll == scroll)
1273 { 1408 {
1274 /* Remove to correctly merge with other items which may exist in inventory */ 1409 /* Remove to correctly merge with other items which may exist in inventory */
1275 remove_ob(newscroll); 1410 remove_ob (newscroll);
1276 esrv_del_item(pl->contr,newscroll->count); 1411 esrv_del_item (pl->contr, newscroll->count);
1277 } 1412 }
1278 newscroll=insert_ob_in_ob(newscroll,pl); 1413 newscroll = insert_ob_in_ob (newscroll, pl);
1279 esrv_send_item(pl, newscroll); 1414 esrv_send_item (pl, newscroll);
1280 success = calc_skill_exp(pl,newscroll, skill); 1415 success = calc_skill_exp (pl, newscroll, skill);
1416 if (!confused)
1281 if(!confused) success *= 2; 1417 success *= 2;
1282 success = success * skill->level; 1418 success = success * skill->level;
1283 return success; 1419 return success;
1284 1420
1285 } else { /* Inscription has failed */ 1421 }
1422 else
1423 { /* Inscription has failed */
1286 1424
1287 if(chosen_spell->level>skill->level || confused) { /*backfire!*/ 1425 if (chosen_spell->level > skill->level || confused)
1288 new_draw_info(NDI_UNIQUE,0,pl, 1426 { /*backfire! */
1289 "Ouch! Your attempt to write a new scroll strains your mind!"); 1427 new_draw_info (NDI_UNIQUE, 0, pl, "Ouch! Your attempt to write a new scroll strains your mind!");
1290 if(random_roll(0, 1, pl, PREFER_LOW)==1) 1428 if (random_roll (0, 1, pl, PREFER_LOW) == 1)
1291 drain_specific_stat(pl,4); 1429 drain_specific_stat (pl, 4);
1292 else { 1430 else
1431 {
1293 confuse_player(pl,pl,99); 1432 confuse_player (pl, pl, 99);
1294 return (-30*chosen_spell->level); 1433 return (-30 * chosen_spell->level);
1295 } 1434 }
1435 }
1296 } else if(random_roll(0, pl->stats.Int-1, pl, PREFER_HIGH) < 15) { 1436 else if (random_roll (0, pl->stats.Int - 1, pl, PREFER_HIGH) < 15)
1297 new_draw_info(NDI_UNIQUE,0,pl, 1437 {
1298 "Your attempt to write a new scroll rattles your mind!"); 1438 new_draw_info (NDI_UNIQUE, 0, pl, "Your attempt to write a new scroll rattles your mind!");
1299 confuse_player(pl,pl,99); 1439 confuse_player (pl, pl, 99);
1440 }
1300 } else 1441 else
1301 new_draw_info(NDI_UNIQUE,0,pl,"You fail to write a new scroll."); 1442 new_draw_info (NDI_UNIQUE, 0, pl, "You fail to write a new scroll.");
1302 } 1443 }
1444 return 0;
1445}
1446
1447/* write_on_item() - wrapper for write_note and write_scroll */
1448int
1449write_on_item (object *pl, const char *params, object *skill)
1450{
1451 object *item;
1452 const char *string = params;
1453 int msgtype;
1454 archetype *skat;
1455
1456 if (pl->type != PLAYER)
1303 return 0; 1457 return 0;
1304}
1305 1458
1306/* write_on_item() - wrapper for write_note and write_scroll */
1307int write_on_item (object *pl,const char *params, object *skill) {
1308 object *item;
1309 const char *string=params;
1310 int msgtype;
1311 archetype *skat;
1312
1313 if(pl->type!=PLAYER) return 0;
1314
1315 if (!params) { 1459 if (!params)
1460 {
1316 params=""; 1461 params = "";
1317 string=params; 1462 string = params;
1318 } 1463 }
1319 skat = get_archetype_by_type_subtype(SKILL, SK_LITERACY); 1464 skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY);
1320 1465
1321 /* Need to be able to read before we can write! */ 1466 /* Need to be able to read before we can write! */
1322 if(!find_skill_by_name(pl,skat->clone.skill)) { 1467 if (!find_skill_by_name (pl, skat->clone.skill))
1323 new_draw_info(NDI_UNIQUE,0,pl, 1468 {
1324 "You must learn to read before you can write!"); 1469 new_draw_info (NDI_UNIQUE, 0, pl, "You must learn to read before you can write!");
1325 return 0; 1470 return 0;
1326 } 1471 }
1327 1472
1328 /* if there is a message then it goes in a book and no message means 1473 /* if there is a message then it goes in a book and no message means
1329 * write active spell into the scroll 1474 * write active spell into the scroll
1330 */ 1475 */
1331 msgtype = (string[0]!='\0') ? BOOK : SCROLL; 1476 msgtype = (string[0] != '\0') ? BOOK : SCROLL;
1332 1477
1333 /* find an item of correct type to write on */ 1478 /* find an item of correct type to write on */
1334 if ( !(item = find_marked_object(pl))){ 1479 if (!(item = find_marked_object (pl)))
1480 {
1335 new_draw_info(NDI_UNIQUE,0,pl,"You don't have any marked item to write on."); 1481 new_draw_info (NDI_UNIQUE, 0, pl, "You don't have any marked item to write on.");
1336 return 0; 1482 return 0;
1337 } 1483 }
1338 1484
1339 if(QUERY_FLAG(item,FLAG_UNPAID)) { 1485 if (QUERY_FLAG (item, FLAG_UNPAID))
1340 new_draw_info(NDI_UNIQUE,0,pl, 1486 {
1341 "You had better pay for that before you write on it."); 1487 new_draw_info (NDI_UNIQUE, 0, pl, "You had better pay for that before you write on it.");
1342 return 0; 1488 return 0;
1343 } 1489 }
1344 if (msgtype != item->type) { 1490 if (msgtype != item->type)
1491 {
1345 new_draw_info_format(NDI_UNIQUE,0,pl,"You have no %s to write on", 1492 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no %s to write on", msgtype == BOOK ? "book" : "scroll");
1346 msgtype==BOOK ? "book" : "scroll");
1347 return 0; 1493 return 0;
1348 } 1494 }
1349 1495
1350 if (msgtype == SCROLL) { 1496 if (msgtype == SCROLL)
1497 {
1351 return write_scroll(pl,item, skill); 1498 return write_scroll (pl, item, skill);
1499 }
1352 } else if (msgtype == BOOK) { 1500 else if (msgtype == BOOK)
1501 {
1353 return write_note(pl,item,string, skill); 1502 return write_note (pl, item, string, skill);
1354 } 1503 }
1355 return 0; 1504 return 0;
1356} 1505}
1357 1506
1358 1507
1359 1508
1360/* find_throw_ob() - if we request an object, then 1509/* find_throw_ob() - if we request an object, then
1364 * (that is "throwable", ie no throwing your skills away!) 1513 * (that is "throwable", ie no throwing your skills away!)
1365 * is the object of choice. Also check to see if object is 1514 * is the object of choice. Also check to see if object is
1366 * 'throwable' (ie not applied cursed obj, worn, etc). 1515 * 'throwable' (ie not applied cursed obj, worn, etc).
1367 */ 1516 */
1368 1517
1518static object *
1369static object *find_throw_ob( object *op, const char *request ) { 1519find_throw_ob (object *op, const char *request)
1520{
1370 object *tmp; 1521 object *tmp;
1371 1522
1372 if(!op) { /* safety */ 1523 if (!op)
1524 { /* safety */
1373 LOG(llevError,"find_throw_ob(): confused! have a NULL thrower!\n"); 1525 LOG (llevError, "find_throw_ob(): confused! have a NULL thrower!\n");
1374 return (object *) NULL; 1526 return (object *) NULL;
1375 } 1527 }
1376 1528
1377 /* prefer marked item */ 1529 /* prefer marked item */
1378 tmp = find_marked_object(op); 1530 tmp = find_marked_object (op);
1379 if (tmp != NULL) { 1531 if (tmp != NULL)
1532 {
1380 /* can't toss invisible or inv-locked items */ 1533 /* can't toss invisible or inv-locked items */
1381 if (tmp->invisible || QUERY_FLAG(tmp, FLAG_INV_LOCKED)) { 1534 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_INV_LOCKED))
1535 {
1382 tmp = NULL; 1536 tmp = NULL;
1383 } 1537 }
1384 } 1538 }
1385 1539
1386 /* look through the inventory */ 1540 /* look through the inventory */
1387 if (tmp == NULL) { 1541 if (tmp == NULL)
1542 {
1388 for (tmp = op->inv; tmp != NULL; tmp = tmp->below) { 1543 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
1544 {
1389 /* can't toss invisible or inv-locked items */ 1545 /* can't toss invisible or inv-locked items */
1390 if (tmp->invisible || QUERY_FLAG(tmp, FLAG_INV_LOCKED)) 1546 if (tmp->invisible || QUERY_FLAG (tmp, FLAG_INV_LOCKED))
1391 continue; 1547 continue;
1392 if (!request 1548 if (!request || !strcmp (query_name (tmp), request) || !strcmp (tmp->name, request))
1393 || !strcmp(query_name(tmp), request)
1394 || !strcmp(tmp->name, request))
1395 break; 1549 break;
1396 } 1550 }
1397 } 1551 }
1398 1552
1399 /* this should prevent us from throwing away 1553 /* this should prevent us from throwing away
1400 * cursed items, worn armour, etc. Only weapons 1554 * cursed items, worn armour, etc. Only weapons
1401 * can be thrown from 'hand'. 1555 * can be thrown from 'hand'.
1402 */ 1556 */
1557 if (!tmp)
1403 if (!tmp) return NULL; 1558 return NULL;
1404 1559
1405 if (QUERY_FLAG(tmp,FLAG_APPLIED)) { 1560 if (QUERY_FLAG (tmp, FLAG_APPLIED))
1561 {
1406 if(tmp->type!=WEAPON) { 1562 if (tmp->type != WEAPON)
1407 new_draw_info_format(NDI_UNIQUE, 0,op, 1563 {
1408 "You can't throw %s.",query_name(tmp)); 1564 new_draw_info_format (NDI_UNIQUE, 0, op, "You can't throw %s.", query_name (tmp));
1409 tmp = NULL; 1565 tmp = NULL;
1566 }
1410 } else if (QUERY_FLAG(tmp,FLAG_CURSED)||QUERY_FLAG(tmp,FLAG_DAMNED)) { 1567 else if (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))
1411 new_draw_info_format(NDI_UNIQUE, 0,op, 1568 {
1412 "The %s sticks to your hand!",query_name(tmp)); 1569 new_draw_info_format (NDI_UNIQUE, 0, op, "The %s sticks to your hand!", query_name (tmp));
1413 tmp = NULL; 1570 tmp = NULL;
1571 }
1414 } else { 1572 else
1573 {
1415 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) { 1574 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
1575 {
1416 LOG (llevError, "BUG: find_throw_ob(): couldn't unapply\n"); 1576 LOG (llevError, "BUG: find_throw_ob(): couldn't unapply\n");
1417 tmp = NULL; 1577 tmp = NULL;
1418 } 1578 }
1419 } 1579 }
1580 }
1420 } else if (QUERY_FLAG(tmp, FLAG_UNPAID)) { 1581 else if (QUERY_FLAG (tmp, FLAG_UNPAID))
1582 {
1421 new_draw_info_format(NDI_UNIQUE, 0, op, "You should pay for the %s first.", query_name(tmp)); 1583 new_draw_info_format (NDI_UNIQUE, 0, op, "You should pay for the %s first.", query_name (tmp));
1422 tmp = NULL; 1584 tmp = NULL;
1423 } 1585 }
1424 1586
1425 if (tmp && QUERY_FLAG (tmp, FLAG_INV_LOCKED)) { 1587 if (tmp && QUERY_FLAG (tmp, FLAG_INV_LOCKED))
1588 {
1426 LOG (llevError, "BUG: find_throw_ob(): object is locked\n"); 1589 LOG (llevError, "BUG: find_throw_ob(): object is locked\n");
1427 tmp=NULL; 1590 tmp = NULL;
1428 } 1591 }
1429 return tmp; 1592 return tmp;
1430} 1593}
1431 1594
1432/* make_throw_ob() We construct the 'carrier' object in 1595/* make_throw_ob() We construct the 'carrier' object in
1433 * which we will insert the object that is being thrown. 1596 * which we will insert the object that is being thrown.
1434 * This combination becomes the 'thrown object'. -b.t. 1597 * This combination becomes the 'thrown object'. -b.t.
1435 */ 1598 */
1436 1599
1600static object *
1437static object *make_throw_ob (object *orig) { 1601make_throw_ob (object *orig)
1602{
1438 object *toss_item; 1603 object *toss_item;
1439 1604
1605 if (!orig)
1440 if(!orig) return NULL; 1606 return NULL;
1441 1607
1442 toss_item=get_object(); 1608 toss_item = get_object ();
1443 if (QUERY_FLAG (orig, FLAG_APPLIED)) { 1609 if (QUERY_FLAG (orig, FLAG_APPLIED))
1610 {
1444 LOG (llevError, "BUG: make_throw_ob(): ob is applied\n"); 1611 LOG (llevError, "BUG: make_throw_ob(): ob is applied\n");
1445 /* insufficient workaround, but better than nothing */ 1612 /* insufficient workaround, but better than nothing */
1446 CLEAR_FLAG (orig, FLAG_APPLIED); 1613 CLEAR_FLAG (orig, FLAG_APPLIED);
1447 } 1614 }
1448 copy_object(orig,toss_item); 1615 copy_object (orig, toss_item);
1449 toss_item->type = THROWN_OBJ; 1616 toss_item->type = THROWN_OBJ;
1450 CLEAR_FLAG(toss_item,FLAG_CHANGING); 1617 CLEAR_FLAG (toss_item, FLAG_CHANGING);
1451 toss_item->stats.dam = 0; /* default damage */ 1618 toss_item->stats.dam = 0; /* default damage */
1452 insert_ob_in_ob(orig,toss_item); 1619 insert_ob_in_ob (orig, toss_item);
1453 return toss_item; 1620 return toss_item;
1454} 1621}
1455 1622
1456 1623
1457/* do_throw() - op throws any object toss_item. This code 1624/* do_throw() - op throws any object toss_item. This code
1458 * was borrowed from fire_bow. 1625 * was borrowed from fire_bow.
1459 * Returns 1 if skill was successfully used, 0 if not 1626 * Returns 1 if skill was successfully used, 0 if not
1460 */ 1627 */
1461 1628
1629static int
1462static int do_throw(object *op, object *part, object *toss_item, int dir, object *skill) { 1630do_throw (object *op, object *part, object *toss_item, int dir, object *skill)
1631{
1463 object *throw_ob=toss_item, *left=NULL; 1632 object *throw_ob = toss_item, *left = NULL;
1464 tag_t left_tag;
1465 int eff_str = 0,maxc,str=op->stats.Str,dam=0; 1633 int eff_str = 0, maxc, str = op->stats.Str, dam = 0;
1466 int pause_f,weight_f=0, mflags; 1634 int pause_f, weight_f = 0, mflags;
1467 float str_factor=1.0,load_factor=1.0,item_factor=1.0; 1635 float str_factor = 1.0, load_factor = 1.0, item_factor = 1.0;
1468 mapstruct *m; 1636 maptile *m;
1469 sint16 sx, sy; 1637 sint16 sx, sy;
1470 tag_t tag;
1471 1638
1472 if(throw_ob==NULL) { 1639 if (throw_ob == NULL)
1640 {
1473 if(op->type==PLAYER) { 1641 if (op->type == PLAYER)
1474 new_draw_info(NDI_UNIQUE, 0,op,"You have nothing to throw."); 1642 new_draw_info (NDI_UNIQUE, 0, op, "You have nothing to throw.");
1475 } 1643
1476 return 0; 1644 return 0;
1477 } 1645 }
1478 if (QUERY_FLAG(throw_ob, FLAG_STARTEQUIP)) { 1646 if (QUERY_FLAG (throw_ob, FLAG_STARTEQUIP))
1647 {
1479 if (op->type==PLAYER) { 1648 if (op->type == PLAYER)
1480 new_draw_info(NDI_UNIQUE, 0, op, "The gods won't let you throw that."); 1649 new_draw_info (NDI_UNIQUE, 0, op, "The gods won't let you throw that.");
1481 } 1650
1482 return 0; 1651 return 0;
1483 } 1652 }
1484 1653
1485 /* Because throwing effectiveness must be reduced by the 1654 /* Because throwing effectiveness must be reduced by the
1486 * encumbrance of the thrower and weight of the object. THus, 1655 * encumbrance of the thrower and weight of the object. THus,
1487 * we use the concept of 'effective strength' as defined below. 1656 * we use the concept of 'effective strength' as defined below.
1488 */ 1657 */
1489 1658
1490 /* if str exceeds MAX_STAT (30, eg giants), lets assign a str_factor > 1 */ 1659 /* if str exceeds MAX_STAT (30, eg giants), lets assign a str_factor > 1 */
1491 if(str>MAX_STAT) { 1660 if (str > MAX_STAT)
1661 {
1492 str_factor = (float) str /(float) MAX_STAT; str = MAX_STAT; 1662 str_factor = (float) str / (float) MAX_STAT;
1493 } 1663 str = MAX_STAT;
1494 1664 }
1665
1495 /* the more we carry, the less we can throw. Limit only on players */ 1666 /* the more we carry, the less we can throw. Limit only on players */
1496 maxc=max_carry[str]*1000; 1667 maxc = max_carry[str] * 1000;
1497 if(op->carrying>maxc&&op->type==PLAYER) 1668 if (op->carrying > maxc && op->type == PLAYER)
1498 load_factor = (float)maxc/(float) op->carrying; 1669 load_factor = (float) maxc / (float) op->carrying;
1499 1670
1500 /* lighter items are thrown harder, farther, faster */ 1671 /* lighter items are thrown harder, farther, faster */
1501 if(throw_ob->weight>0) 1672 if (throw_ob->weight > 0)
1502 item_factor = (float) maxc/(float) (3.0 * throw_ob->weight); 1673 item_factor = (float) maxc / (float) (3.0 * throw_ob->weight);
1674 else
1503 else { /* 0 or negative weight?!? Odd object, can't throw it */ 1675 { /* 0 or negative weight?!? Odd object, can't throw it */
1504 new_draw_info_format(NDI_UNIQUE, 0,op,"You can't throw %s.\n", 1676 new_draw_info_format (NDI_UNIQUE, 0, op, "You can't throw %s.\n", query_name (throw_ob));
1505 query_name(throw_ob));
1506 return 0; 1677 return 0;
1507 }
1508 1678 }
1679
1509 eff_str = (int) (str * (load_factor<1.0?load_factor:1.0)); 1680 eff_str = (int) (str * (load_factor < 1.0 ? load_factor : 1.0));
1510 eff_str = (int) ((float) eff_str * item_factor * str_factor); 1681 eff_str = (int) ((float) eff_str * item_factor * str_factor);
1511 1682
1512 /* alas, arrays limit us to a value of MAX_STAT (30). Use str_factor to 1683 /* alas, arrays limit us to a value of MAX_STAT (30). Use str_factor to
1513 * account for super-strong throwers. */ 1684 * account for super-strong throwers. */
1514 if(eff_str>MAX_STAT) eff_str=MAX_STAT; 1685 if (eff_str > MAX_STAT)
1686 eff_str = MAX_STAT;
1515 1687
1516#ifdef DEBUG_THROW 1688#ifdef DEBUG_THROW
1517 LOG(llevDebug,"%s carries %d, eff_str=%d\n",op->name,op->carrying,eff_str); 1689 LOG (llevDebug, "%s carries %d, eff_str=%d\n", op->name, op->carrying, eff_str);
1518 LOG(llevDebug," max_c=%d, item_f=%f, load_f=%f, str=%d\n",maxc, 1690 LOG (llevDebug, " max_c=%d, item_f=%f, load_f=%f, str=%d\n", maxc, item_factor, load_factor, op->stats.Str);
1519 item_factor,load_factor,op->stats.Str);
1520 LOG(llevDebug," str_factor=%f\n",str_factor); 1691 LOG (llevDebug, " str_factor=%f\n", str_factor);
1521 LOG(llevDebug," item %s weight= %d\n",throw_ob->name,throw_ob->weight); 1692 LOG (llevDebug, " item %s weight= %d\n", throw_ob->name, throw_ob->weight);
1522#endif 1693#endif
1523 1694
1524 /* 3 things here prevent a throw, you aimed at your feet, you 1695 /* 3 things here prevent a throw, you aimed at your feet, you
1525 * have no effective throwing strength, or you threw at something 1696 * have no effective throwing strength, or you threw at something
1526 * that flying objects can't get through. 1697 * that flying objects can't get through.
1527 */ 1698 */
1528 mflags = get_map_flags(part->map,&m, part->x+freearr_x[dir],part->y+freearr_y[dir],&sx,&sy); 1699 mflags = get_map_flags (part->map, &m, part->x + freearr_x[dir], part->y + freearr_y[dir], &sx, &sy);
1529 1700
1530 if(!dir || (eff_str <= 1) || (mflags & P_OUT_OF_MAP) || 1701 if (!dir || (eff_str <= 1) || (mflags & P_OUT_OF_MAP) || (GET_MAP_MOVE_BLOCK (m, sx, sy) & MOVE_FLY_LOW))
1531 (GET_MAP_MOVE_BLOCK(m, sx, sy) & MOVE_FLY_LOW)) { 1702 {
1532 1703
1533 /* bounces off 'wall', and drops to feet */ 1704 /* bounces off 'wall', and drops to feet */
1534 remove_ob(throw_ob); 1705 remove_ob (throw_ob);
1535 throw_ob->x = part->x; throw_ob->y = part->y; 1706 throw_ob->x = part->x;
1707 throw_ob->y = part->y;
1536 insert_ob_in_map(throw_ob,part->map,op,0); 1708 insert_ob_in_map (throw_ob, part->map, op, 0);
1537 if(op->type==PLAYER) { 1709 if (op->type == PLAYER)
1710 {
1538 if(eff_str<=1) { 1711 if (eff_str <= 1)
1539 new_draw_info_format(NDI_UNIQUE, 0,op, 1712 {
1540 "Your load is so heavy you drop %s to the ground.", 1713 new_draw_info_format (NDI_UNIQUE, 0, op, "Your load is so heavy you drop %s to the ground.", query_name (throw_ob));
1541 query_name(throw_ob));
1542 } 1714 }
1543 else if(!dir) { 1715 else if (!dir)
1716 {
1544 new_draw_info_format(NDI_UNIQUE, 0,op,"You throw %s at the ground.", 1717 new_draw_info_format (NDI_UNIQUE, 0, op, "You throw %s at the ground.", query_name (throw_ob));
1545 query_name(throw_ob));
1546 } 1718 }
1547 else 1719 else
1548 new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); 1720 new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1549 } 1721 }
1550 return 0; 1722 return 0;
1551 } /* if object can't be thrown */ 1723 } /* if object can't be thrown */
1552 1724
1553 left = throw_ob; /* these are throwing objects left to the player */ 1725 left = throw_ob; /* these are throwing objects left to the player */
1554 left_tag = left->count;
1555 1726
1556 /* sometimes get_split_ob can't split an object (because op->nrof==0?) 1727 /* sometimes get_split_ob can't split an object (because op->nrof==0?)
1557 * and returns NULL. We must use 'left' then 1728 * and returns NULL. We must use 'left' then
1558 */ 1729 */
1559 1730
1560 if((throw_ob = get_split_ob(throw_ob, 1))==NULL) { 1731 if ((throw_ob = get_split_ob (throw_ob, 1)) == NULL)
1732 {
1561 throw_ob = left; 1733 throw_ob = left;
1562 remove_ob(left); 1734 remove_ob (left);
1563 if (op->type==PLAYER) 1735 if (op->type == PLAYER)
1564 esrv_del_item(op->contr, left->count); 1736 esrv_del_item (op->contr, left->count);
1565 } 1737 }
1566 else if (op->type==PLAYER) { 1738 else if (op->type == PLAYER)
1567 if (was_destroyed (left, left_tag)) 1739 {
1740 if (left->destroyed ())
1568 esrv_del_item(op->contr, left_tag); 1741 esrv_del_item (op->contr, left->count);
1569 else 1742 else
1570 esrv_update_item(UPD_NROF, op, left); 1743 esrv_update_item (UPD_NROF, op, left);
1571 } 1744 }
1572 1745
1573 /* special case: throwing powdery substances like dust, dirt */ 1746 /* special case: throwing powdery substances like dust, dirt */
1574 if(throw_ob->type == POTION && throw_ob->subtype == POT_DUST) { 1747 if (throw_ob->type == POTION && throw_ob->subtype == POT_DUST)
1748 {
1575 cast_dust(op,throw_ob,dir); 1749 cast_dust (op, throw_ob, dir);
1576 return 1; 1750 return 1;
1577 } 1751 }
1578 1752
1579 /* Make a thrown object -- insert real object in a 'carrier' object. 1753 /* Make a thrown object -- insert real object in a 'carrier' object.
1580 * If unsuccessfull at making the "thrown_obj", we just reinsert 1754 * If unsuccessfull at making the "thrown_obj", we just reinsert
1581 * the original object back into inventory and exit 1755 * the original object back into inventory and exit
1582 */ 1756 */
1583 if((toss_item = make_throw_ob(throw_ob))) { 1757 if ((toss_item = make_throw_ob (throw_ob)))
1758 {
1584 throw_ob = toss_item; 1759 throw_ob = toss_item;
1585 throw_ob->skill = skill->skill; 1760 throw_ob->skill = skill->skill;
1761 }
1762 else
1586 } 1763 {
1587 else {
1588 insert_ob_in_ob(throw_ob,op); 1764 insert_ob_in_ob (throw_ob, op);
1589 return 0; 1765 return 0;
1590 } 1766 }
1591 1767
1592 set_owner(throw_ob,op); 1768 set_owner (throw_ob, op);
1593 /* At some point in the attack code, the actual real object (op->inv) 1769 /* At some point in the attack code, the actual real object (op->inv)
1594 * becomes the hitter. As such, we need to make sure that has a proper 1770 * becomes the hitter. As such, we need to make sure that has a proper
1595 * owner value so exp goes to the right place. 1771 * owner value so exp goes to the right place.
1596 */ 1772 */
1597 set_owner(throw_ob->inv,op); 1773 set_owner (throw_ob->inv, op);
1598 throw_ob->direction=dir; 1774 throw_ob->direction = dir;
1599 throw_ob->x = part->x; 1775 throw_ob->x = part->x;
1600 throw_ob->y = part->y; 1776 throw_ob->y = part->y;
1601 1777
1602 /* the damage bonus from the force of the throw */ 1778 /* the damage bonus from the force of the throw */
1603 dam = (int) (str_factor * dam_bonus[eff_str]); 1779 dam = (int) (str_factor * dam_bonus[eff_str]);
1604 1780
1605 /* Now, lets adjust the properties of the thrown_ob. */ 1781 /* Now, lets adjust the properties of the thrown_ob. */
1606 1782
1607 /* how far to fly */ 1783 /* how far to fly */
1608 throw_ob->last_sp = (eff_str*3)/5; 1784 throw_ob->last_sp = (eff_str * 3) / 5;
1609 1785
1610 /* speed */ 1786 /* speed */
1611 throw_ob->speed = (speed_bonus[eff_str]+1.0)/1.5; 1787 throw_ob->speed = (speed_bonus[eff_str] + 1.0) / 1.5;
1612 throw_ob->speed = MIN(1.0,throw_ob->speed); /* no faster than an arrow! */ 1788 throw_ob->speed = MIN (1.0, throw_ob->speed); /* no faster than an arrow! */
1613 1789
1614 /* item damage. Eff_str and item weight influence damage done */ 1790 /* item damage. Eff_str and item weight influence damage done */
1615 weight_f = (throw_ob->weight/2000)>MAX_STAT?MAX_STAT:(throw_ob->weight/2000); 1791 weight_f = (throw_ob->weight / 2000) > MAX_STAT ? MAX_STAT : (throw_ob->weight / 2000);
1616 throw_ob->stats.dam += (dam/3) + dam_bonus[weight_f] 1792 throw_ob->stats.dam += (dam / 3) + dam_bonus[weight_f] + (throw_ob->weight / 15000) - 2;
1617 + (throw_ob->weight/15000) - 2;
1618 1793
1619 /* chance of breaking. Proportional to force used and weight of item */ 1794 /* chance of breaking. Proportional to force used and weight of item */
1620 throw_ob->stats.food = (dam/2) + (throw_ob->weight/60000); 1795 throw_ob->stats.food = (dam / 2) + (throw_ob->weight / 60000);
1621 1796
1622 /* replace 25 with a call to clone.arch wc? messes up w/ NPC */ 1797 /* replace 25 with a call to clone.arch wc? messes up w/ NPC */
1623 throw_ob->stats.wc = 25 - dex_bonus[op->stats.Dex] 1798 throw_ob->stats.wc = 25 - dex_bonus[op->stats.Dex] - thaco_bonus[eff_str] - skill->level;
1624 - thaco_bonus[eff_str] - skill->level;
1625
1626 1799
1800
1627 /* the properties of objects which are meant to be thrown (ie dart, 1801 /* the properties of objects which are meant to be thrown (ie dart,
1628 * throwing knife, etc) will differ from ordinary items. Lets tailor 1802 * throwing knife, etc) will differ from ordinary items. Lets tailor
1629 * this stuff in here. 1803 * this stuff in here.
1630 */ 1804 */
1631 1805
1632 if(QUERY_FLAG(throw_ob->inv,FLAG_IS_THROWN)) { 1806 if (QUERY_FLAG (throw_ob->inv, FLAG_IS_THROWN))
1807 {
1633 throw_ob->last_sp += eff_str/3; /* fly a little further */ 1808 throw_ob->last_sp += eff_str / 3; /* fly a little further */
1634 throw_ob->stats.dam += throw_ob->inv->stats.dam + throw_ob->magic + 2; 1809 throw_ob->stats.dam += throw_ob->inv->stats.dam + throw_ob->magic + 2;
1635 throw_ob->stats.wc -= throw_ob->magic + throw_ob->inv->stats.wc; 1810 throw_ob->stats.wc -= throw_ob->magic + throw_ob->inv->stats.wc;
1636 /* only throw objects get directional faces */ 1811 /* only throw objects get directional faces */
1637 if(GET_ANIM_ID(throw_ob) && NUM_ANIMATIONS(throw_ob)) 1812 if (GET_ANIM_ID (throw_ob) && NUM_ANIMATIONS (throw_ob))
1638 SET_ANIMATION(throw_ob, dir); 1813 SET_ANIMATION (throw_ob, dir);
1639 } else { 1814 }
1815 else
1816 {
1640 /* some materials will adjust properties.. */ 1817 /* some materials will adjust properties.. */
1641 if(throw_ob->material&M_LEATHER) { 1818 if (throw_ob->material & M_LEATHER)
1819 {
1642 throw_ob->stats.dam -= 1; 1820 throw_ob->stats.dam -= 1;
1643 throw_ob->stats.food -= 10; 1821 throw_ob->stats.food -= 10;
1644 } 1822 }
1645 if(throw_ob->material&M_GLASS) throw_ob->stats.food += 60; 1823 if (throw_ob->material & M_GLASS)
1646 1824 throw_ob->stats.food += 60;
1825
1647 if(throw_ob->material&M_ORGANIC) { 1826 if (throw_ob->material & M_ORGANIC)
1827 {
1648 throw_ob->stats.dam -= 3; 1828 throw_ob->stats.dam -= 3;
1649 throw_ob->stats.food += 55; 1829 throw_ob->stats.food += 55;
1650 } 1830 }
1651 if(throw_ob->material&M_PAPER||throw_ob->material&M_CLOTH) { 1831 if (throw_ob->material & M_PAPER || throw_ob->material & M_CLOTH)
1652 throw_ob->stats.dam -= 5; throw_ob->speed *= 0.8;
1653 throw_ob->stats.wc += 3; throw_ob->stats.food -= 30;
1654 } 1832 {
1833 throw_ob->stats.dam -= 5;
1834 throw_ob->speed *= 0.8;
1835 throw_ob->stats.wc += 3;
1836 throw_ob->stats.food -= 30;
1837 }
1655 /* light obj have more wind resistance, fly slower*/ 1838 /* light obj have more wind resistance, fly slower */
1656 if(throw_ob->weight>500) throw_ob->speed *= 0.8; 1839 if (throw_ob->weight > 500)
1657 if(throw_ob->weight>50) throw_ob->speed *= 0.5; 1840 throw_ob->speed *= 0.8;
1658 1841 if (throw_ob->weight > 50)
1659 } /* else tailor thrown object */ 1842 throw_ob->speed *= 0.5;
1660 1843
1844 } /* else tailor thrown object */
1845
1661 /* some limits, and safeties (needed?) */ 1846 /* some limits, and safeties (needed?) */
1662 if(throw_ob->stats.dam<0) throw_ob->stats.dam=0; 1847 if (throw_ob->stats.dam < 0)
1663 if(throw_ob->last_sp>eff_str) throw_ob->last_sp=eff_str; 1848 throw_ob->stats.dam = 0;
1664 if(throw_ob->stats.food<0) throw_ob->stats.food=0; 1849 if (throw_ob->last_sp > eff_str)
1665 if(throw_ob->stats.food>100) throw_ob->stats.food=100; 1850 throw_ob->last_sp = eff_str;
1666 if(throw_ob->stats.wc>30) throw_ob->stats.wc=30; 1851 if (throw_ob->stats.food < 0)
1852 throw_ob->stats.food = 0;
1853 if (throw_ob->stats.food > 100)
1854 throw_ob->stats.food = 100;
1855 if (throw_ob->stats.wc > 30)
1856 throw_ob->stats.wc = 30;
1667 1857
1668 /* how long to pause the thrower. Higher values mean less pause */ 1858 /* how long to pause the thrower. Higher values mean less pause */
1669 pause_f = ((2*eff_str)/3)+20+skill->level; 1859 pause_f = ((2 * eff_str) / 3) + 20 + skill->level;
1670 1860
1671 /* Put a lower limit on this */ 1861 /* Put a lower limit on this */
1672 if (pause_f < 10) pause_f=10; 1862 if (pause_f < 10)
1673 if (pause_f > 100) pause_f=100; 1863 pause_f = 10;
1864 if (pause_f > 100)
1865 pause_f = 100;
1674 1866
1675 /* Changed in 0.94.2 - the calculation before was really goofy. 1867 /* Changed in 0.94.2 - the calculation before was really goofy.
1676 * In short summary, a throw can take anywhere between speed 5 and 1868 * In short summary, a throw can take anywhere between speed 5 and
1677 * speed 0.5 1869 * speed 0.5
1678 */ 1870 */
1679 op->speed_left -= 50 / pause_f; 1871 op->speed_left -= 50 / pause_f;
1680 1872
1681 update_ob_speed(throw_ob); 1873 update_ob_speed (throw_ob);
1682 throw_ob->speed_left = 0; 1874 throw_ob->speed_left = 0;
1683 throw_ob->map = part->map; 1875 throw_ob->map = part->map;
1684 1876
1685 throw_ob->move_type = MOVE_FLY_LOW; 1877 throw_ob->move_type = MOVE_FLY_LOW;
1686 throw_ob->move_on = MOVE_FLY_LOW | MOVE_WALK; 1878 throw_ob->move_on = MOVE_FLY_LOW | MOVE_WALK;
1687 1879
1688#if 0 1880#if 0
1689 /* need to put in a good sound for this */ 1881 /* need to put in a good sound for this */
1690 play_sound_map(op->map, op->x, op->y, SOUND_THROW_OBJ); 1882 play_sound_map (op->map, op->x, op->y, SOUND_THROW_OBJ);
1691#endif 1883#endif
1884
1692/* Lauwenmark - Now we can call the associated script_throw event (if any) */ 1885/* Lauwenmark - Now we can call the associated script_throw event (if any) */
1693 INVOKE_OBJECT (THROW, throw_ob, ARG_OBJECT (op)); 1886 INVOKE_OBJECT (THROW, throw_ob, ARG_OBJECT (op));
1694#ifdef DEBUG_THROW 1887#ifdef DEBUG_THROW
1695 LOG(llevDebug," pause_f=%d \n",pause_f); 1888 LOG (llevDebug, " pause_f=%d \n", pause_f);
1696 LOG(llevDebug," %s stats: wc=%d dam=%d dist=%d spd=%f break=%d\n", 1889 LOG (llevDebug, " %s stats: wc=%d dam=%d dist=%d spd=%f break=%d\n",
1697 throw_ob->name,throw_ob->stats.wc,throw_ob->stats.dam, 1890 throw_ob->name, throw_ob->stats.wc, throw_ob->stats.dam, throw_ob->last_sp, throw_ob->speed, throw_ob->stats.food);
1698 throw_ob->last_sp,throw_ob->speed,throw_ob->stats.food);
1699 LOG(llevDebug,"inserting tossitem (%d) into map\n",throw_ob->count); 1891 LOG (llevDebug, "inserting tossitem (%d) into map\n", throw_ob->count);
1700#endif 1892#endif
1701 tag = throw_ob->count;
1702 insert_ob_in_map(throw_ob,part->map,op,0); 1893 insert_ob_in_map (throw_ob, part->map, op, 0);
1703 if (!was_destroyed (throw_ob, tag)) 1894
1895 if (!throw_ob->destroyed ())
1704 move_arrow(throw_ob); 1896 move_arrow (throw_ob);
1897
1705 return 1; 1898 return 1;
1706} 1899}
1707 1900
1901int
1708int skill_throw (object *op, object *part, int dir, const char *params, object *skill) { 1902skill_throw (object *op, object *part, int dir, const char *params, object *skill)
1903{
1709 object *throw_ob; 1904 object *throw_ob;
1710 1905
1711 if(op->type==PLAYER) 1906 if (op->type == PLAYER)
1712 throw_ob = find_throw_ob(op,params); 1907 throw_ob = find_throw_ob (op, params);
1713 else 1908 else
1714 throw_ob = find_mon_throw_ob(op); 1909 throw_ob = find_mon_throw_ob (op);
1715 1910
1716 return do_throw(op,part, throw_ob,dir, skill); 1911 return do_throw (op, part, throw_ob, dir, skill);
1717} 1912}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines