1 | /* |
1 | /* |
2 | * static char *rcsid_skills_c = |
2 | * static char *rcsid_skills_c = |
3 | * "$Id: skills.C,v 1.5 2006/08/29 05:03:55 root Exp $"; |
3 | * "$Id: skills.C,v 1.6 2006/08/29 08:01:38 root Exp $"; |
4 | */ |
4 | */ |
5 | /* |
5 | /* |
6 | CrossFire, A Multiplayer game for X-windows |
6 | CrossFire, A Multiplayer game for X-windows |
7 | |
7 | |
8 | Copyright (C) 2003 Mark Wedel & Crossfire Development Team |
8 | Copyright (C) 2003 Mark Wedel & Crossfire Development Team |
… | |
… | |
44 | /* Only prohibit stealing if the player does not have a free |
44 | /* Only prohibit stealing if the player does not have a free |
45 | * hand available and in fact does have hands. |
45 | * hand available and in fact does have hands. |
46 | */ |
46 | */ |
47 | if(op->type==PLAYER && op->body_used[BODY_ARMS] <=0 && |
47 | if(op->type==PLAYER && op->body_used[BODY_ARMS] <=0 && |
48 | op->body_info[BODY_ARMS]) { |
48 | op->body_info[BODY_ARMS]) { |
49 | new_draw_info(NDI_UNIQUE, 0,op,"But you have no free hands to steal with!"); |
49 | new_draw_info(NDI_UNIQUE, 0,op,"But you have no free hands to steal with!"); |
50 | return -1; |
50 | return -1; |
51 | } |
51 | } |
52 | |
52 | |
53 | /* ADJUSTMENTS */ |
53 | /* ADJUSTMENTS */ |
54 | |
54 | |
55 | /* Its harder to steal from hostile beings! */ |
55 | /* Its harder to steal from hostile beings! */ |
56 | if(!QUERY_FLAG(victim, FLAG_UNAGGRESSIVE)) roll = roll/2; |
56 | if(!QUERY_FLAG(victim, FLAG_UNAGGRESSIVE)) 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 | if(equip->type==WEAPON&&QUERY_FLAG(equip,FLAG_APPLIED)) { |
69 | if(equip->type==WEAPON&&QUERY_FLAG(equip,FLAG_APPLIED)) { |
70 | roll -= equip->weight/10000; |
70 | roll -= equip->weight/10000; |
71 | } |
71 | } |
72 | if(equip->type==BOW&&QUERY_FLAG(equip,FLAG_APPLIED)) |
72 | if(equip->type==BOW&&QUERY_FLAG(equip,FLAG_APPLIED)) |
73 | roll -= equip->weight/5000; |
73 | roll -= equip->weight/5000; |
74 | if(equip->type==SHIELD&&QUERY_FLAG(equip,FLAG_APPLIED)) { |
74 | if(equip->type==SHIELD&&QUERY_FLAG(equip,FLAG_APPLIED)) { |
75 | roll -= equip->weight/2000; |
75 | roll -= equip->weight/2000; |
76 | } |
76 | } |
77 | if(equip->type==ARMOUR&&QUERY_FLAG(equip,FLAG_APPLIED)) |
77 | if(equip->type==ARMOUR&&QUERY_FLAG(equip,FLAG_APPLIED)) |
78 | roll -= equip->weight/5000; |
78 | roll -= equip->weight/5000; |
79 | if(equip->type==GLOVES&&QUERY_FLAG(equip,FLAG_APPLIED)) |
79 | if(equip->type==GLOVES&&QUERY_FLAG(equip,FLAG_APPLIED)) |
80 | roll -= equip->weight/100; |
80 | roll -= equip->weight/100; |
81 | } |
81 | } |
82 | if(roll<0) roll=0; |
82 | if(roll<0) roll=0; |
83 | return roll; |
83 | return roll; |
84 | } |
84 | } |
85 | |
85 | |
… | |
… | |
104 | /* if the victim is aware of a thief in the area (FLAG_NO_STEAL set on them) |
104 | /* 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 |
105 | * they will try to prevent stealing if they can. Only unseen theives will |
106 | * have much chance of success. |
106 | * have much chance of success. |
107 | */ |
107 | */ |
108 | if(op->type!=PLAYER && QUERY_FLAG(op,FLAG_NO_STEAL)) { |
108 | if(op->type!=PLAYER && QUERY_FLAG(op,FLAG_NO_STEAL)) { |
109 | if(can_detect_enemy(op,who,&rv)) { |
109 | if(can_detect_enemy(op,who,&rv)) { |
110 | npc_call_help(op); |
110 | npc_call_help(op); |
111 | CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); |
111 | CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); |
112 | new_draw_info(NDI_UNIQUE, 0,who,"Your attempt is prevented!"); |
112 | new_draw_info(NDI_UNIQUE, 0,who,"Your attempt is prevented!"); |
113 | return 0; |
113 | return 0; |
114 | } else /* help npc to detect thief next time by raising its wisdom */ |
114 | } else /* help npc to detect thief next time by raising its wisdom */ |
115 | op->stats.Wis += (op->stats.Int/5)+1; |
115 | op->stats.Wis += (op->stats.Int/5)+1; |
116 | if (op->stats.Wis > MAX_STAT) op->stats.Wis = MAX_STAT; |
116 | if (op->stats.Wis > MAX_STAT) op->stats.Wis = MAX_STAT; |
117 | } |
117 | } |
118 | if (op->type == PLAYER && QUERY_FLAG(op, FLAG_WIZ)) { |
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"); |
119 | new_draw_info(NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n"); |
120 | return 0; |
120 | return 0; |
121 | } |
121 | } |
122 | #ifdef PROHIBIT_PLAYERKILL |
122 | #ifdef PROHIBIT_PLAYERKILL |
123 | if(op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful)) { |
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"); |
124 | new_draw_info(NDI_UNIQUE, 0, who, "You can't steal from other players!\n"); |
125 | return 0; |
125 | return 0; |
… | |
… | |
132 | #endif |
132 | #endif |
133 | |
133 | |
134 | |
134 | |
135 | /* Ok then, go thru their inventory, stealing */ |
135 | /* Ok then, go thru their inventory, stealing */ |
136 | for(tmp = op->inv; tmp != NULL; tmp = next) { |
136 | for(tmp = op->inv; tmp != NULL; tmp = next) { |
137 | next = tmp->below; |
137 | next = tmp->below; |
138 | |
138 | |
139 | /* you can't steal worn items, starting items, wiz stuff, |
139 | /* you can't steal worn items, starting items, wiz stuff, |
140 | * innate abilities, or items w/o a type. Generally |
140 | * innate abilities, or items w/o a type. Generally |
141 | * speaking, the invisibility flag prevents experience or |
141 | * speaking, the invisibility flag prevents experience or |
142 | * abilities from being stolen since these types are currently |
142 | * abilities from being stolen since these types are currently |
143 | * always invisible objects. I was implicit here so as to prevent |
143 | * always invisible objects. I was implicit here so as to prevent |
144 | * future possible problems. -b.t. |
144 | * future possible problems. -b.t. |
145 | * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL |
145 | * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL |
146 | * already -b.t. |
146 | * already -b.t. |
147 | */ |
147 | */ |
148 | |
148 | |
149 | if (QUERY_FLAG(tmp,FLAG_WAS_WIZ) || QUERY_FLAG(tmp, FLAG_APPLIED) |
149 | if (QUERY_FLAG(tmp,FLAG_WAS_WIZ) || QUERY_FLAG(tmp, FLAG_APPLIED) |
150 | || !(tmp->type) |
150 | || !(tmp->type) |
151 | || tmp->type == EXPERIENCE || tmp->type == SPELL |
151 | || tmp->type == EXPERIENCE || tmp->type == SPELL |
152 | || QUERY_FLAG(tmp,FLAG_STARTEQUIP) |
152 | || QUERY_FLAG(tmp,FLAG_STARTEQUIP) |
153 | || QUERY_FLAG(tmp,FLAG_NO_STEAL) |
153 | || QUERY_FLAG(tmp,FLAG_NO_STEAL) |
154 | || tmp->invisible ) continue; |
154 | || tmp->invisible ) continue; |
155 | |
155 | |
156 | /* Okay, try stealing this item. Dependent on dexterity of thief, |
156 | /* Okay, try stealing this item. Dependent on dexterity of thief, |
157 | * skill level, see the adj_stealroll fctn for more detail. |
157 | * skill level, see the adj_stealroll fctn for more detail. |
158 | */ |
158 | */ |
159 | |
159 | |
160 | roll=die_roll(2, 100, who, PREFER_LOW)/2; /* weighted 1-100 */ |
160 | roll=die_roll(2, 100, who, PREFER_LOW)/2; /* weighted 1-100 */ |
161 | |
161 | |
162 | if((chance=adj_stealchance(who,op,(stats_value+skill->level * 10 - op->level * 3)))==-1) |
162 | if((chance=adj_stealchance(who,op,(stats_value+skill->level * 10 - op->level * 3)))==-1) |
163 | return 0; |
163 | return 0; |
164 | else if (roll < chance ) { |
164 | else if (roll < chance ) { |
165 | tag_t tmp_count = tmp->count; |
165 | tag_t tmp_count = tmp->count; |
166 | |
166 | |
167 | pick_up(who, tmp); |
167 | pick_up(who, tmp); |
168 | /* need to see if the player actually stole this item - |
168 | /* need to see if the player actually stole this item - |
169 | * if it is in the players inv, assume it is. This prevents |
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 |
170 | * abuses where the player can not carry the item, so just |
171 | * keeps stealing it over and over. |
171 | * keeps stealing it over and over. |
172 | */ |
172 | */ |
173 | if (was_destroyed(tmp, tmp_count) || tmp->env != op) { |
173 | if (was_destroyed(tmp, tmp_count) || tmp->env != op) { |
174 | /* for players, play_sound: steals item */ |
174 | /* for players, play_sound: steals item */ |
175 | success = tmp; |
175 | success = tmp; |
176 | CLEAR_FLAG(tmp, FLAG_INV_LOCKED); |
176 | CLEAR_FLAG(tmp, FLAG_INV_LOCKED); |
177 | |
177 | |
178 | /* Don't delete it from target player until we know |
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, |
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. |
180 | * as it's possible that it got merged when picked up. |
181 | */ |
181 | */ |
182 | if (op->type == PLAYER) |
182 | if (op->type == PLAYER) |
183 | esrv_del_item(op->contr, tmp_count); |
183 | esrv_del_item(op->contr, tmp_count); |
184 | } |
184 | } |
185 | break; |
185 | break; |
186 | } |
186 | } |
187 | } /* for loop looking for an item */ |
187 | } /* for loop looking for an item */ |
188 | |
188 | |
189 | if (!tmp) { |
189 | if (!tmp) { |
190 | new_draw_info_format(NDI_UNIQUE, 0, who, "%s%s has nothing you can steal!", |
190 | new_draw_info_format(NDI_UNIQUE, 0, who, "%s%s has nothing you can steal!", |
191 | op->type == PLAYER ? "" : "The ", query_name(op)); |
191 | op->type == PLAYER ? "" : "The ", query_name(op)); |
192 | return 0; |
192 | return 0; |
193 | } |
193 | } |
194 | |
194 | |
195 | /* If you arent high enough level, you might get something BUT |
195 | /* If you arent high enough level, you might get something BUT |
196 | * the victim will notice your stealing attempt. Ditto if you |
196 | * the victim will notice your stealing attempt. Ditto if you |
197 | * attempt to steal something heavy off them, they're bound to notice |
197 | * attempt to steal something heavy off them, they're bound to notice |
198 | */ |
198 | */ |
199 | |
199 | |
200 | if((roll>=skill->level) || !chance |
200 | if((roll>=skill->level) || !chance |
201 | ||(tmp && tmp->weight>(250*(random_roll(0, stats_value+skill->level * 10-1, who, PREFER_LOW))))) { |
201 | ||(tmp && tmp->weight>(250*(random_roll(0, stats_value+skill->level * 10-1, who, PREFER_LOW))))) { |
202 | |
202 | |
203 | /* victim figures out where the thief is! */ |
203 | /* victim figures out where the thief is! */ |
204 | if(who->hide) make_visible(who); |
204 | if(who->hide) make_visible(who); |
205 | |
205 | |
206 | if(op->type != PLAYER) { |
206 | if(op->type != PLAYER) { |
207 | /* The unaggressives look after themselves 8) */ |
207 | /* The unaggressives look after themselves 8) */ |
208 | if(who->type==PLAYER) { |
208 | if(who->type==PLAYER) { |
209 | npc_call_help(op); |
209 | npc_call_help(op); |
210 | new_draw_info_format(NDI_UNIQUE, 0,who, |
210 | new_draw_info_format(NDI_UNIQUE, 0,who, |
211 | "%s notices your attempted pilfering!",query_name(op)); |
211 | "%s notices your attempted pilfering!",query_name(op)); |
212 | } |
212 | } |
213 | CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); |
213 | CLEAR_FLAG(op, FLAG_UNAGGRESSIVE); |
214 | /* all remaining npc items are guarded now. Set flag NO_STEAL |
214 | /* all remaining npc items are guarded now. Set flag NO_STEAL |
215 | * on the victim. |
215 | * on the victim. |
216 | */ |
216 | */ |
217 | SET_FLAG(op,FLAG_NO_STEAL); |
217 | SET_FLAG(op,FLAG_NO_STEAL); |
218 | } else { /* stealing from another player */ |
218 | } else { /* stealing from another player */ |
219 | char buf[MAX_BUF]; |
219 | char buf[MAX_BUF]; |
220 | /* Notify the other player */ |
220 | /* Notify the other player */ |
221 | if (success && who->stats.Int > random_roll(0, 19, op, PREFER_LOW)) { |
221 | if (success && who->stats.Int > random_roll(0, 19, op, PREFER_LOW)) { |
222 | sprintf(buf, "Your %s is missing!", query_name(success)); |
222 | sprintf(buf, "Your %s is missing!", query_name(success)); |
223 | } else { |
223 | } else { |
224 | sprintf(buf, "Your pack feels strangely lighter."); |
224 | sprintf(buf, "Your pack feels strangely lighter."); |
225 | } |
225 | } |
226 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
226 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
227 | if (!success) { |
227 | if (!success) { |
228 | if (who->invisible) { |
228 | if (who->invisible) { |
229 | sprintf(buf, "you feel itchy fingers getting at your pack."); |
229 | sprintf(buf, "you feel itchy fingers getting at your pack."); |
230 | } else { |
230 | } else { |
231 | sprintf(buf, "%s looks very shifty.", query_name(who)); |
231 | sprintf(buf, "%s looks very shifty.", query_name(who)); |
232 | } |
232 | } |
233 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
233 | new_draw_info(NDI_UNIQUE, 0,op,buf); |
234 | } |
234 | } |
235 | } /* else stealing from another player */ |
235 | } /* else stealing from another player */ |
236 | /* play_sound("stop! thief!"); kindofthing */ |
236 | /* play_sound("stop! thief!"); kindofthing */ |
237 | } /* if you weren't 100% successful */ |
237 | } /* if you weren't 100% successful */ |
238 | return success? 1:0; |
238 | return success? 1:0; |
239 | } |
239 | } |
240 | |
240 | |
241 | |
241 | |
… | |
… | |
248 | |
248 | |
249 | x = op->x + freearr_x[dir]; |
249 | x = op->x + freearr_x[dir]; |
250 | y = op->y + freearr_y[dir]; |
250 | y = op->y + freearr_y[dir]; |
251 | |
251 | |
252 | if(dir == 0) { |
252 | if(dir == 0) { |
253 | /* Can't steal from ourself! */ |
253 | /* Can't steal from ourself! */ |
254 | return 0; |
254 | return 0; |
255 | } |
255 | } |
256 | |
256 | |
257 | m = op->map; |
257 | m = op->map; |
258 | mflags = get_map_flags(m, &m ,x,y, &x, &y); |
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, |
259 | /* Out of map - can't do it. If nothing alive on this space, |
260 | * don't need to look any further. |
260 | * don't need to look any further. |
261 | */ |
261 | */ |
262 | if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) |
262 | if ((mflags & P_OUT_OF_MAP) || !(mflags & P_IS_ALIVE)) |
263 | return 0; |
263 | return 0; |
264 | |
264 | |
265 | /* If player can't move onto the space, can't steal from it. */ |
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))) |
266 | if (OB_TYPE_MOVE_BLOCK(op, GET_MAP_MOVE_BLOCK(m, x, y))) |
267 | return 0; |
267 | return 0; |
268 | |
268 | |
269 | /* Find the topmost object at this spot */ |
269 | /* Find the topmost object at this spot */ |
270 | for(tmp = get_map_ob(m,x,y); |
270 | for(tmp = get_map_ob(m,x,y); |
271 | tmp != NULL && tmp->above != NULL; |
271 | tmp != NULL && tmp->above != NULL; |
272 | tmp = tmp->above); |
272 | tmp = tmp->above); |
273 | |
273 | |
274 | /* For all the stacked objects at this point, attempt a steal */ |
274 | /* For all the stacked objects at this point, attempt a steal */ |
275 | for(; tmp != NULL; tmp = next) { |
275 | for(; tmp != NULL; tmp = next) { |
276 | next = tmp->below; |
276 | next = tmp->below; |
277 | /* Minor hack--for multi square beings - make sure we get |
277 | /* Minor hack--for multi square beings - make sure we get |
278 | * the 'head' coz 'tail' objects have no inventory! - b.t. |
278 | * the 'head' coz 'tail' objects have no inventory! - b.t. |
279 | */ |
279 | */ |
280 | if (tmp->head) tmp=tmp->head; |
280 | if (tmp->head) tmp=tmp->head; |
281 | |
281 | |
282 | if(tmp->type!=PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) continue; |
282 | if(tmp->type!=PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) continue; |
283 | |
283 | |
284 | /* do not reveal hidden DMs */ |
284 | /* do not reveal hidden DMs */ |
285 | if (tmp->type == PLAYER && QUERY_FLAG(tmp, FLAG_WIZ) && tmp->contr->hidden) continue; |
285 | if (tmp->type == PLAYER && QUERY_FLAG(tmp, FLAG_WIZ) && tmp->contr->hidden) continue; |
286 | if (attempt_steal(tmp, op, skill)) { |
286 | if (attempt_steal(tmp, op, skill)) { |
287 | if (tmp->type==PLAYER) /* no xp for stealing from another player */ |
287 | if (tmp->type==PLAYER) /* no xp for stealing from another player */ |
288 | return 0; |
288 | return 0; |
289 | |
289 | |
290 | /* no xp for stealing from pets (of players) */ |
290 | /* no xp for stealing from pets (of players) */ |
291 | if (QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE) { |
291 | if (QUERY_FLAG(tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE) { |
292 | object *owner = get_owner(tmp); |
292 | object *owner = get_owner(tmp); |
293 | if (owner != NULL && owner->type == PLAYER) |
293 | if (owner != NULL && owner->type == PLAYER) |
294 | return 0; |
294 | return 0; |
295 | } |
295 | } |
296 | |
296 | |
297 | // reduce monster experience by experience we gained, as to |
297 | // reduce monster experience by experience we gained, as to |
298 | // limit the amount of exp that can be gained by stealing from monsters |
298 | // limit the amount of exp that can be gained by stealing from monsters |
299 | // (jessies gave ~20,000,000 exp otherwise. |
299 | // (jessies gave ~20,000,000 exp otherwise. |
300 | int exp = calc_skill_exp (op, tmp, skill); |
300 | int exp = calc_skill_exp (op, tmp, skill); |
301 | exp = MIN (tmp->stats.exp, exp); |
301 | exp = MIN (tmp->stats.exp, exp); |
302 | tmp->stats.exp -= exp; |
302 | tmp->stats.exp -= exp; |
303 | return exp; |
303 | return exp; |
304 | } |
304 | } |
305 | } |
305 | } |
306 | return 0; |
306 | return 0; |
307 | } |
307 | } |
308 | |
308 | |
309 | static int attempt_pick_lock (object *door, object *pl, object *skill) |
309 | static int attempt_pick_lock (object *door, object *pl, object *skill) |
… | |
… | |
316 | * Dependent on dexterity/skill SK_level of the player and |
316 | * Dependent on dexterity/skill SK_level of the player and |
317 | * the map level difficulty. |
317 | * the map level difficulty. |
318 | */ |
318 | */ |
319 | number = (die_roll(2, 40, pl, PREFER_LOW)-2)/2; |
319 | number = (die_roll(2, 40, pl, PREFER_LOW)-2)/2; |
320 | if (number < (pl->stats.Dex + skill->level - difficulty)) { |
320 | if (number < (pl->stats.Dex + skill->level - difficulty)) { |
321 | remove_door(door); |
321 | remove_door(door); |
322 | success = 1; |
322 | success = 1; |
323 | } else if (door->inv && (door->inv->type==RUNE || door->inv->type==TRAP)) { /* set off any traps? */ |
323 | } else if (door->inv && (door->inv->type==RUNE || door->inv->type==TRAP)) { /* set off any traps? */ |
324 | spring_trap(door->inv,pl); |
324 | spring_trap(door->inv,pl); |
325 | } |
325 | } |
326 | return success; |
326 | return success; |
327 | } |
327 | } |
328 | |
328 | |
329 | |
329 | |
… | |
… | |
339 | |
339 | |
340 | if(!dir) dir=pl->facing; |
340 | if(!dir) dir=pl->facing; |
341 | |
341 | |
342 | /* For all the stacked objects at this point find a door*/ |
342 | /* For all the stacked objects at this point find a door*/ |
343 | if (out_of_map(pl->map,x,y)) { |
343 | if (out_of_map(pl->map,x,y)) { |
344 | new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); |
344 | new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); |
345 | return 0; |
345 | return 0; |
346 | } |
346 | } |
347 | |
347 | |
348 | for(tmp=get_map_ob(pl->map,x,y); tmp; tmp=tmp->above) |
348 | for(tmp=get_map_ob(pl->map,x,y); tmp; tmp=tmp->above) |
349 | if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) break; |
349 | if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) break; |
350 | |
350 | |
351 | if (!tmp) { |
351 | if (!tmp) { |
352 | new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); |
352 | new_draw_info(NDI_UNIQUE, 0,pl,"There is no lock there."); |
353 | return 0; |
353 | return 0; |
354 | } |
354 | } |
355 | if (tmp->type == LOCKED_DOOR) { |
355 | if (tmp->type == LOCKED_DOOR) { |
356 | new_draw_info(NDI_UNIQUE, 0,pl, "You can't pick that lock!"); |
356 | new_draw_info(NDI_UNIQUE, 0,pl, "You can't pick that lock!"); |
357 | return 0; |
357 | return 0; |
358 | } |
358 | } |
359 | |
359 | |
360 | if (!tmp->move_block) { |
360 | if (!tmp->move_block) { |
361 | new_draw_info(NDI_UNIQUE, 0,pl,"The door has no lock!"); |
361 | new_draw_info(NDI_UNIQUE, 0,pl,"The door has no lock!"); |
362 | return 0; |
362 | return 0; |
363 | } |
363 | } |
364 | |
364 | |
365 | if (attempt_pick_lock(tmp, pl, skill)) { |
365 | if (attempt_pick_lock(tmp, pl, skill)) { |
366 | new_draw_info(NDI_UNIQUE, 0,pl,"You pick the lock."); |
366 | new_draw_info(NDI_UNIQUE, 0,pl,"You pick the lock."); |
367 | return calc_skill_exp(pl,NULL, skill); |
367 | return calc_skill_exp(pl,NULL, skill); |
368 | } else { |
368 | } else { |
369 | new_draw_info(NDI_UNIQUE, 0,pl, "You fail to pick the lock."); |
369 | new_draw_info(NDI_UNIQUE, 0,pl, "You fail to pick the lock."); |
370 | return 0; |
370 | return 0; |
371 | } |
371 | } |
372 | } |
372 | } |
373 | |
373 | |
374 | |
374 | |
375 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
375 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
… | |
… | |
384 | static int attempt_hide(object *op, object *skill) { |
384 | static int attempt_hide(object *op, object *skill) { |
385 | int number,difficulty=op->map->difficulty; |
385 | int number,difficulty=op->map->difficulty; |
386 | int terrain = hideability(op); |
386 | int terrain = hideability(op); |
387 | |
387 | |
388 | if(terrain<-10) /* not enough cover here */ |
388 | if(terrain<-10) /* not enough cover here */ |
389 | return 0; |
389 | return 0; |
390 | |
390 | |
391 | /* Hiding success and duration dependant on skill level, |
391 | /* Hiding success and duration dependant on skill level, |
392 | * op->stats.Dex, map difficulty and terrain. |
392 | * op->stats.Dex, map difficulty and terrain. |
393 | */ |
393 | */ |
394 | |
394 | |
395 | number = (die_roll(2, 25, op, PREFER_LOW)-2)/2; |
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))) { |
396 | if(!stand_near_hostile(op) && (number < (op->stats.Dex + skill->level + terrain - difficulty))) { |
397 | op->invisible += 100; /* set the level of 'hiddeness' */ |
397 | op->invisible += 100; /* set the level of 'hiddeness' */ |
398 | if(op->type==PLAYER) |
398 | if(op->type==PLAYER) |
399 | op->contr->tmp_invis=1; |
399 | op->contr->tmp_invis=1; |
400 | op->hide=1; |
400 | op->hide=1; |
401 | return 1; |
401 | return 1; |
402 | } |
402 | } |
403 | return 0; |
403 | return 0; |
404 | } |
404 | } |
405 | |
405 | |
406 | /* patched this to take terrain into consideration */ |
406 | /* patched this to take terrain into consideration */ |
… | |
… | |
409 | |
409 | |
410 | /* the preliminaries -- Can we really hide now? */ |
410 | /* the preliminaries -- Can we really hide now? */ |
411 | /* this keeps monsters from using invisibilty spells and hiding */ |
411 | /* this keeps monsters from using invisibilty spells and hiding */ |
412 | |
412 | |
413 | if (QUERY_FLAG(op, FLAG_MAKE_INVIS)) { |
413 | if (QUERY_FLAG(op, FLAG_MAKE_INVIS)) { |
414 | new_draw_info(NDI_UNIQUE, 0,op,"You don't need to hide while invisible!"); |
414 | new_draw_info(NDI_UNIQUE, 0,op,"You don't need to hide while invisible!"); |
415 | return 0; |
415 | return 0; |
416 | } else if (!op->hide && op->invisible>0 && op->type == PLAYER) { |
416 | } else if (!op->hide && op->invisible>0 && op->type == PLAYER) { |
417 | new_draw_info(NDI_UNIQUE, 0,op,"Your attempt to hide breaks the invisibility spell!"); |
417 | new_draw_info(NDI_UNIQUE, 0,op,"Your attempt to hide breaks the invisibility spell!"); |
418 | make_visible(op); |
418 | make_visible(op); |
419 | } |
419 | } |
420 | |
420 | |
421 | if(op->invisible>(50*skill->level)) { |
421 | if(op->invisible>(50*skill->level)) { |
422 | new_draw_info(NDI_UNIQUE,0,op,"You are as hidden as you can get."); |
422 | new_draw_info(NDI_UNIQUE,0,op,"You are as hidden as you can get."); |
423 | return 0; |
423 | return 0; |
424 | } |
424 | } |
425 | |
425 | |
426 | if(attempt_hide(op, skill)) { |
426 | if(attempt_hide(op, skill)) { |
427 | new_draw_info(NDI_UNIQUE, 0,op,"You hide in the shadows."); |
427 | new_draw_info(NDI_UNIQUE, 0,op,"You hide in the shadows."); |
428 | update_object(op,UP_OBJ_FACE); |
428 | update_object(op,UP_OBJ_FACE); |
429 | return calc_skill_exp(op, NULL, skill); |
429 | return calc_skill_exp(op, NULL, skill); |
430 | } |
430 | } |
431 | new_draw_info(NDI_UNIQUE,0,op,"You fail to conceal yourself."); |
431 | new_draw_info(NDI_UNIQUE,0,op,"You fail to conceal yourself."); |
432 | return 0; |
432 | return 0; |
433 | } |
433 | } |
434 | |
434 | |
… | |
… | |
464 | * that cares about the move_type being flying. |
464 | * that cares about the move_type being flying. |
465 | */ |
465 | */ |
466 | pl->move_type |= MOVE_FLY_LOW; |
466 | pl->move_type |= MOVE_FLY_LOW; |
467 | |
467 | |
468 | for(i=0;i<=spaces;i++) { |
468 | for(i=0;i<=spaces;i++) { |
469 | x = pl->x + dx; |
469 | x = pl->x + dx; |
470 | y = pl->y + dy; |
470 | y = pl->y + dy; |
471 | m = pl->map; |
471 | m = pl->map; |
472 | |
472 | |
473 | mflags = get_map_flags(m, &m, x, y, &x, &y); |
473 | mflags = get_map_flags(m, &m, x, y, &x, &y); |
474 | |
474 | |
475 | if (mflags & P_OUT_OF_MAP) { |
475 | if (mflags & P_OUT_OF_MAP) { |
476 | (void) stop_jump(pl,i,spaces); |
476 | (void) stop_jump(pl,i,spaces); |
477 | return 0; |
477 | return 0; |
478 | } |
478 | } |
479 | if (OB_TYPE_MOVE_BLOCK(pl, GET_MAP_MOVE_BLOCK(m, x, y))) { |
479 | if (OB_TYPE_MOVE_BLOCK(pl, GET_MAP_MOVE_BLOCK(m, x, y))) { |
480 | new_draw_info(NDI_UNIQUE, 0,pl,"Your jump is blocked."); |
480 | new_draw_info(NDI_UNIQUE, 0,pl,"Your jump is blocked."); |
481 | stop_jump(pl,i,spaces); |
481 | stop_jump(pl,i,spaces); |
482 | return 0; |
482 | return 0; |
483 | } |
483 | } |
484 | |
484 | |
485 | for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { |
485 | for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { |
486 | /* Jump into creature */ |
486 | /* Jump into creature */ |
487 | if(QUERY_FLAG(tmp, FLAG_MONSTER) |
487 | if(QUERY_FLAG(tmp, FLAG_MONSTER) |
488 | || (tmp->type==PLAYER && (!QUERY_FLAG(tmp, FLAG_WIZ) || !tmp->contr->hidden))) { |
488 | || (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.", |
489 | new_draw_info_format(NDI_UNIQUE, 0,pl,"You jump into %s%s.", |
490 | tmp->type == PLAYER ? "" : "the ", tmp->name); |
490 | tmp->type == PLAYER ? "" : "the ", tmp->name); |
491 | if(tmp->type!=PLAYER || |
491 | if(tmp->type!=PLAYER || |
492 | (pl->type==PLAYER && pl->contr->party==NULL) || |
492 | (pl->type==PLAYER && pl->contr->party==NULL) || |
493 | (pl->type==PLAYER && tmp->type==PLAYER && |
493 | (pl->type==PLAYER && tmp->type==PLAYER && |
494 | 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 */ |
495 | exp = skill_attack(tmp,pl,pl->facing,"kicked", skill); /* pl makes an attack */ |
496 | stop_jump(pl,i,spaces); |
496 | stop_jump(pl,i,spaces); |
497 | return exp; /* note that calc_skill_exp() is already called by skill_attack() */ |
497 | return exp; /* note that calc_skill_exp() is already called by skill_attack() */ |
498 | } |
498 | } |
499 | /* If the space has fly on set (no matter what the space is), |
499 | /* If the space has fly on set (no matter what the space is), |
500 | * we should get the effects - after all, the player is |
500 | * we should get the effects - after all, the player is |
501 | * effectively flying. |
501 | * effectively flying. |
502 | */ |
502 | */ |
503 | if (tmp->move_on & MOVE_FLY_LOW) { |
503 | if (tmp->move_on & MOVE_FLY_LOW) { |
504 | pl->x = x; |
504 | pl->x = x; |
505 | pl->y = y; |
505 | pl->y = y; |
506 | pl->map = m; |
506 | pl->map = m; |
507 | stop_jump(pl,i,spaces); |
507 | stop_jump(pl,i,spaces); |
508 | return calc_skill_exp(pl,NULL, skill); |
508 | return calc_skill_exp(pl,NULL, skill); |
509 | } |
509 | } |
510 | } |
510 | } |
511 | pl->x = x; |
511 | pl->x = x; |
512 | pl->y = y; |
512 | pl->y = y; |
513 | pl->map = m; |
513 | pl->map = m; |
514 | } |
514 | } |
515 | stop_jump(pl,i,spaces); |
515 | stop_jump(pl,i,spaces); |
516 | return calc_skill_exp(pl,NULL, skill); |
516 | return calc_skill_exp(pl,NULL, skill); |
517 | } |
517 | } |
518 | |
518 | |
… | |
… | |
532 | str = str ? str : 10; |
532 | str = str ? str : 10; |
533 | |
533 | |
534 | stats=str*str*str*dex * skill->level; |
534 | stats=str*str*str*dex * skill->level; |
535 | |
535 | |
536 | if(pl->carrying!=0) /* don't want div by zero !! */ |
536 | if(pl->carrying!=0) /* don't want div by zero !! */ |
537 | spaces=(int) (stats/pl->carrying); |
537 | spaces=(int) (stats/pl->carrying); |
538 | else |
538 | else |
539 | spaces=2; /* pl has no objects - gets the far jump */ |
539 | spaces=2; /* pl has no objects - gets the far jump */ |
540 | |
540 | |
541 | if(spaces>2) |
541 | if(spaces>2) |
542 | spaces = 2; |
542 | spaces = 2; |
543 | else if(spaces==0) { |
543 | else if(spaces==0) { |
544 | new_draw_info(NDI_UNIQUE, 0,pl,"You are carrying too much weight to jump."); |
544 | new_draw_info(NDI_UNIQUE, 0,pl,"You are carrying too much weight to jump."); |
545 | return 0; |
545 | return 0; |
546 | } |
546 | } |
547 | return attempt_jump(pl,dir,spaces, skill); |
547 | return attempt_jump(pl,dir,spaces, skill); |
548 | } |
548 | } |
549 | |
549 | |
550 | |
550 | |
… | |
… | |
561 | static int do_skill_detect_curse(object *pl, object *skill) { |
561 | static int do_skill_detect_curse(object *pl, object *skill) { |
562 | object *tmp; |
562 | object *tmp; |
563 | int success=0; |
563 | int success=0; |
564 | |
564 | |
565 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
565 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
566 | if (!tmp->invisible |
566 | if (!tmp->invisible |
567 | && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) |
567 | && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) |
568 | && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && |
568 | && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && |
569 | tmp->item_power < skill->level) { |
569 | tmp->item_power < skill->level) { |
570 | SET_FLAG(tmp,FLAG_KNOWN_CURSED); |
570 | SET_FLAG(tmp,FLAG_KNOWN_CURSED); |
571 | esrv_update_item(UPD_FLAGS, pl, tmp); |
571 | esrv_update_item(UPD_FLAGS, pl, tmp); |
572 | success+= calc_skill_exp(pl,tmp, skill); |
572 | success+= calc_skill_exp(pl,tmp, skill); |
573 | } |
573 | } |
574 | |
574 | |
575 | /* Check ground, too, but only objects the player could pick up */ |
575 | /* 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) |
576 | for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) |
577 | if (can_pick(pl, tmp) && |
577 | if (can_pick(pl, tmp) && |
578 | !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && |
578 | !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && |
579 | !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) |
579 | !QUERY_FLAG(tmp,FLAG_KNOWN_CURSED) |
580 | && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && |
580 | && (QUERY_FLAG(tmp,FLAG_CURSED) || QUERY_FLAG(tmp,FLAG_DAMNED)) && |
581 | tmp->item_power < skill->level) { |
581 | tmp->item_power < skill->level) { |
582 | SET_FLAG(tmp,FLAG_KNOWN_CURSED); |
582 | SET_FLAG(tmp,FLAG_KNOWN_CURSED); |
583 | esrv_update_item(UPD_FLAGS, pl, tmp); |
583 | esrv_update_item(UPD_FLAGS, pl, tmp); |
584 | success+= calc_skill_exp(pl,tmp, skill); |
584 | success+= calc_skill_exp(pl,tmp, skill); |
585 | } |
585 | } |
586 | |
586 | |
587 | return success; |
587 | return success; |
588 | } |
588 | } |
589 | |
589 | |
590 | static int do_skill_detect_magic(object *pl, object *skill) { |
590 | static int do_skill_detect_magic(object *pl, object *skill) { |
591 | object *tmp; |
591 | object *tmp; |
592 | int success=0; |
592 | int success=0; |
593 | |
593 | |
594 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
594 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
595 | if(!tmp->invisible |
595 | if(!tmp->invisible |
596 | && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) |
596 | && !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) |
597 | && (is_magical(tmp)) && tmp->item_power < skill->level) { |
597 | && (is_magical(tmp)) && tmp->item_power < skill->level) { |
598 | SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); |
598 | SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); |
599 | esrv_update_item(UPD_FLAGS, pl, tmp); |
599 | esrv_update_item(UPD_FLAGS, pl, tmp); |
600 | success+=calc_skill_exp(pl,tmp, skill); |
600 | success+=calc_skill_exp(pl,tmp, skill); |
601 | } |
601 | } |
602 | |
602 | |
603 | /* Check ground, too, but like above, only if the object can be picked up*/ |
603 | /* 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) |
604 | for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) |
605 | if (can_pick(pl, tmp) && |
605 | if (can_pick(pl, tmp) && |
606 | !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && |
606 | !QUERY_FLAG(tmp,FLAG_IDENTIFIED) && |
607 | !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) |
607 | !QUERY_FLAG(tmp,FLAG_KNOWN_MAGICAL) |
608 | && (is_magical(tmp)) && tmp->item_power < skill->level) { |
608 | && (is_magical(tmp)) && tmp->item_power < skill->level) { |
609 | SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); |
609 | SET_FLAG(tmp,FLAG_KNOWN_MAGICAL); |
610 | esrv_update_item(UPD_FLAGS, pl, tmp); |
610 | esrv_update_item(UPD_FLAGS, pl, tmp); |
611 | success+=calc_skill_exp(pl,tmp, skill); |
611 | success+=calc_skill_exp(pl,tmp, skill); |
612 | } |
612 | } |
613 | |
613 | |
614 | return success; |
614 | return success; |
615 | } |
615 | } |
616 | |
616 | |
617 | /* Helper function for do_skill_ident, so that we can loop |
617 | /* Helper function for do_skill_ident, so that we can loop |
… | |
… | |
660 | static int do_skill_ident(object *pl, int obj_class, object *skill) { |
660 | static int do_skill_ident(object *pl, int obj_class, object *skill) { |
661 | object *tmp; |
661 | object *tmp; |
662 | int success=0; |
662 | int success=0; |
663 | |
663 | |
664 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
664 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
665 | success+=do_skill_ident2(tmp,pl,obj_class, skill); |
665 | success+=do_skill_ident2(tmp,pl,obj_class, skill); |
666 | /* check the ground */ |
666 | /* check the ground */ |
667 | |
667 | |
668 | for(tmp=get_map_ob(pl->map,pl->x,pl->y);tmp;tmp=tmp->above) |
668 | 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); |
669 | success+=do_skill_ident2(tmp,pl,obj_class, skill); |
670 | |
670 | |
671 | return success; |
671 | return success; |
672 | } |
672 | } |
673 | |
673 | |
674 | int skill_ident(object *pl, object *skill) { |
674 | int skill_ident(object *pl, object *skill) { |
675 | int success=0; |
675 | int success=0; |
… | |
… | |
677 | if(pl->type != PLAYER) return 0; /* only players will skill-identify */ |
677 | if(pl->type != PLAYER) return 0; /* only players will skill-identify */ |
678 | |
678 | |
679 | new_draw_info(NDI_UNIQUE, 0,pl,"You look at the objects nearby..."); |
679 | new_draw_info(NDI_UNIQUE, 0,pl,"You look at the objects nearby..."); |
680 | |
680 | |
681 | switch (skill->subtype) { |
681 | switch (skill->subtype) { |
682 | case SK_SMITHERY: |
682 | case SK_SMITHERY: |
683 | success += do_skill_ident(pl,WEAPON, skill) + do_skill_ident(pl,ARMOUR, skill) |
683 | 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) |
684 | + 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) |
685 | + 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) |
686 | + do_skill_ident(pl,GIRDLE,skill) + do_skill_ident(pl,HELMET,skill) |
687 | + do_skill_ident(pl,GLOVES,skill); |
687 | + do_skill_ident(pl,GLOVES,skill); |
688 | break; |
688 | break; |
689 | |
689 | |
690 | case SK_BOWYER: |
690 | case SK_BOWYER: |
691 | success += do_skill_ident(pl,BOW,skill) + do_skill_ident(pl,ARROW,skill); |
691 | success += do_skill_ident(pl,BOW,skill) + do_skill_ident(pl,ARROW,skill); |
692 | break; |
692 | break; |
693 | |
693 | |
694 | case SK_ALCHEMY: |
694 | case SK_ALCHEMY: |
695 | success += do_skill_ident(pl,POTION,skill) + do_skill_ident(pl,POISON,skill) |
695 | success += do_skill_ident(pl,POTION,skill) + do_skill_ident(pl,POISON,skill) |
696 | + do_skill_ident(pl,CONTAINER,skill) |
696 | + do_skill_ident(pl,CONTAINER,skill) |
697 | + 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; |
698 | break; |
699 | |
699 | |
700 | case SK_WOODSMAN: |
700 | case SK_WOODSMAN: |
701 | success += do_skill_ident(pl,FOOD,skill) + do_skill_ident(pl,DRINK,skill) |
701 | success += do_skill_ident(pl,FOOD,skill) + do_skill_ident(pl,DRINK,skill) |
702 | + do_skill_ident(pl,FLESH,skill); |
702 | + do_skill_ident(pl,FLESH,skill); |
703 | break; |
703 | break; |
704 | |
704 | |
705 | case SK_JEWELER: |
705 | case SK_JEWELER: |
706 | success += do_skill_ident(pl,GEM,skill) + do_skill_ident(pl,RING,skill) + |
706 | success += do_skill_ident(pl,GEM,skill) + do_skill_ident(pl,RING,skill) + |
707 | do_skill_ident(pl,AMULET,skill); |
707 | do_skill_ident(pl,AMULET,skill); |
708 | break; |
708 | break; |
709 | |
709 | |
710 | case SK_LITERACY: |
710 | case SK_LITERACY: |
711 | success += do_skill_ident(pl,SPELLBOOK,skill) |
711 | success += do_skill_ident(pl,SPELLBOOK,skill) |
712 | + 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; |
713 | break; |
714 | |
714 | |
715 | case SK_THAUMATURGY: |
715 | case SK_THAUMATURGY: |
716 | success += do_skill_ident(pl,WAND,skill) + do_skill_ident(pl,ROD,skill) |
716 | success += do_skill_ident(pl,WAND,skill) + do_skill_ident(pl,ROD,skill) |
717 | + do_skill_ident(pl,HORN,skill); |
717 | + do_skill_ident(pl,HORN,skill); |
718 | break; |
718 | break; |
719 | |
719 | |
720 | case SK_DET_CURSE: |
720 | case SK_DET_CURSE: |
721 | success = do_skill_detect_curse(pl,skill); |
721 | success = do_skill_detect_curse(pl,skill); |
722 | if(success) |
722 | if(success) |
723 | new_draw_info(NDI_UNIQUE, 0,pl,"...and discover cursed items!"); |
723 | new_draw_info(NDI_UNIQUE, 0,pl,"...and discover cursed items!"); |
724 | break; |
724 | break; |
725 | |
725 | |
726 | case SK_DET_MAGIC: |
726 | case SK_DET_MAGIC: |
727 | success = do_skill_detect_magic(pl,skill); |
727 | success = do_skill_detect_magic(pl,skill); |
728 | if(success) |
728 | if(success) |
729 | new_draw_info(NDI_UNIQUE, 0,pl, |
729 | new_draw_info(NDI_UNIQUE, 0,pl, |
730 | "...and discover items imbued with mystic forces!"); |
730 | "...and discover items imbued with mystic forces!"); |
731 | break; |
731 | break; |
732 | |
732 | |
733 | default: |
733 | default: |
734 | LOG(llevError,"Error: bad call to skill_ident()\n"); |
734 | LOG(llevError,"Error: bad call to skill_ident()\n"); |
735 | return 0; |
735 | return 0; |
736 | break; |
736 | break; |
737 | } |
737 | } |
738 | if(!success) { |
738 | if(!success) { |
739 | new_draw_info(NDI_UNIQUE, 0,pl,"...and learn nothing more."); |
739 | new_draw_info(NDI_UNIQUE, 0,pl,"...and learn nothing more."); |
740 | } |
740 | } |
741 | return success; |
741 | return success; |
742 | } |
742 | } |
743 | |
743 | |
744 | |
744 | |
… | |
… | |
760 | if (mflags & P_OUT_OF_MAP) return 0; |
760 | if (mflags & P_OUT_OF_MAP) return 0; |
761 | |
761 | |
762 | /* Save some processing - we have the flag already anyways |
762 | /* Save some processing - we have the flag already anyways |
763 | */ |
763 | */ |
764 | if (!(mflags & P_IS_ALIVE)) { |
764 | if (!(mflags & P_IS_ALIVE)) { |
765 | new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
765 | new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
766 | return 0; |
766 | return 0; |
767 | } |
767 | } |
768 | |
768 | |
769 | for(tmp=get_map_ob(m,x,y);tmp;tmp=tmp->above) { |
769 | for(tmp=get_map_ob(m,x,y);tmp;tmp=tmp->above) { |
770 | /* can't persuade players - return because there is nothing else |
770 | /* can't persuade players - return because there is nothing else |
771 | * on that space to charm. Same for multi space monsters and |
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 |
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 |
773 | * is no reason to do further processing since they should be the |
774 | * only monster on the space. |
774 | * only monster on the space. |
775 | */ |
775 | */ |
776 | if(tmp->type==PLAYER) return 0; |
776 | if(tmp->type==PLAYER) return 0; |
777 | if(tmp->more || tmp->head) return 0; |
777 | if(tmp->more || tmp->head) return 0; |
778 | if(tmp->msg) return 0; |
778 | if(tmp->msg) return 0; |
779 | |
779 | |
780 | if(QUERY_FLAG(tmp,FLAG_MONSTER)) break; |
780 | if(QUERY_FLAG(tmp,FLAG_MONSTER)) break; |
781 | } |
781 | } |
782 | |
782 | |
783 | if (!tmp) { |
783 | if (!tmp) { |
784 | new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
784 | new_draw_info(NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
785 | return 0; |
785 | return 0; |
786 | } |
786 | } |
787 | |
787 | |
788 | new_draw_info_format(NDI_UNIQUE, |
788 | new_draw_info_format(NDI_UNIQUE, |
789 | 0,pl, "You orate to the %s.",query_name(tmp)); |
789 | 0,pl, "You orate to the %s.",query_name(tmp)); |
790 | |
790 | |
791 | /* the following conditions limit who may be 'charmed' */ |
791 | /* the following conditions limit who may be 'charmed' */ |
792 | |
792 | |
793 | /* it's hostile! */ |
793 | /* it's hostile! */ |
794 | if(!QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && !QUERY_FLAG(tmp, FLAG_FRIENDLY)) { |
794 | if(!QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && !QUERY_FLAG(tmp, FLAG_FRIENDLY)) { |
795 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
795 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
796 | "Too bad the %s isn't listening!\n",query_name(tmp)); |
796 | "Too bad the %s isn't listening!\n",query_name(tmp)); |
797 | return 0; |
797 | return 0; |
798 | } |
798 | } |
799 | |
799 | |
800 | /* it's already allied! */ |
800 | /* it's already allied! */ |
801 | if(QUERY_FLAG(tmp,FLAG_FRIENDLY)&&(tmp->attack_movement==PETMOVE)){ |
801 | if(QUERY_FLAG(tmp,FLAG_FRIENDLY)&&(tmp->attack_movement==PETMOVE)){ |
802 | if(get_owner(tmp)==pl) { |
802 | if(get_owner(tmp)==pl) { |
803 | new_draw_info(NDI_UNIQUE, 0,pl, |
803 | new_draw_info(NDI_UNIQUE, 0,pl, |
804 | "Your follower loves your speech.\n"); |
804 | "Your follower loves your speech.\n"); |
805 | return 0; |
805 | return 0; |
806 | } else if (skill->level > tmp->level) { |
806 | } else if (skill->level > tmp->level) { |
807 | /* you steal the follower. Perhaps we should really look at the |
807 | /* you steal the follower. Perhaps we should really look at the |
808 | * level of the owner above? |
808 | * level of the owner above? |
809 | */ |
809 | */ |
810 | set_owner(tmp,pl); |
810 | set_owner(tmp,pl); |
811 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
811 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
812 | "You convince the %s to follow you instead!\n", |
812 | "You convince the %s to follow you instead!\n", |
813 | query_name(tmp)); |
813 | query_name(tmp)); |
814 | /* Abuse fix - don't give exp since this can otherwise |
814 | /* Abuse fix - don't give exp since this can otherwise |
815 | * be used by a couple players to gets lots of exp. |
815 | * be used by a couple players to gets lots of exp. |
816 | */ |
816 | */ |
817 | return 0; |
817 | return 0; |
818 | } else { |
818 | } else { |
819 | /* In this case, you can't steal it from the other player */ |
819 | /* In this case, you can't steal it from the other player */ |
820 | return 0; |
820 | return 0; |
821 | } |
821 | } |
822 | } /* Creature was already a pet of someone */ |
822 | } /* Creature was already a pet of someone */ |
823 | |
823 | |
824 | chance=skill->level*2+(pl->stats.Cha-2*tmp->stats.Int)/2; |
824 | chance=skill->level*2+(pl->stats.Cha-2*tmp->stats.Int)/2; |
825 | |
825 | |
826 | /* Ok, got a 'sucker' lets try to make them a follower */ |
826 | /* 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)) { |
827 | if(chance>0 && tmp->level<(random_roll(0, chance-1, pl, PREFER_HIGH)-1)) { |
828 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
828 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
829 | "You convince the %s to become your follower.\n", |
829 | "You convince the %s to become your follower.\n", |
830 | query_name(tmp)); |
830 | query_name(tmp)); |
831 | |
831 | |
832 | set_owner(tmp,pl); |
832 | set_owner(tmp,pl); |
833 | tmp->stats.exp = 0; |
833 | tmp->stats.exp = 0; |
834 | add_friendly_object(tmp); |
834 | add_friendly_object(tmp); |
835 | SET_FLAG(tmp,FLAG_FRIENDLY); |
835 | SET_FLAG(tmp,FLAG_FRIENDLY); |
836 | tmp->attack_movement = PETMOVE; |
836 | tmp->attack_movement = PETMOVE; |
837 | return calc_skill_exp(pl,tmp, skill); |
837 | return calc_skill_exp(pl,tmp, skill); |
838 | } |
838 | } |
839 | /* Charm failed. Creature may be angry now */ |
839 | /* 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)) { |
840 | 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, |
841 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
842 | "Your speech angers the %s!\n",query_name(tmp)); |
842 | "Your speech angers the %s!\n",query_name(tmp)); |
843 | if(QUERY_FLAG(tmp,FLAG_FRIENDLY)) { |
843 | if(QUERY_FLAG(tmp,FLAG_FRIENDLY)) { |
844 | CLEAR_FLAG(tmp,FLAG_FRIENDLY); |
844 | CLEAR_FLAG(tmp,FLAG_FRIENDLY); |
845 | remove_friendly_object(tmp); |
845 | remove_friendly_object(tmp); |
846 | tmp->attack_movement = 0; /* needed? */ |
846 | tmp->attack_movement = 0; /* needed? */ |
847 | } |
847 | } |
848 | CLEAR_FLAG(tmp,FLAG_UNAGGRESSIVE); |
848 | CLEAR_FLAG(tmp,FLAG_UNAGGRESSIVE); |
849 | } |
849 | } |
850 | return 0; /* Fall through - if we get here, we didn't charm anything */ |
850 | return 0; /* Fall through - if we get here, we didn't charm anything */ |
851 | } |
851 | } |
852 | |
852 | |
853 | /* Singing() -this skill allows the player to pacify nearby creatures. |
853 | /* Singing() -this skill allows the player to pacify nearby creatures. |
… | |
… | |
868 | |
868 | |
869 | if(pl->type!=PLAYER) return 0; /* only players use this skill */ |
869 | if(pl->type!=PLAYER) return 0; /* only players use this skill */ |
870 | |
870 | |
871 | new_draw_info_format(NDI_UNIQUE,0,pl, "You sing."); |
871 | new_draw_info_format(NDI_UNIQUE,0,pl, "You sing."); |
872 | for(i=0;i<MIN(skill->level,SIZEOFFREE);i++) { |
872 | for(i=0;i<MIN(skill->level,SIZEOFFREE);i++) { |
873 | x = pl->x+freearr_x[i]; |
873 | x = pl->x+freearr_x[i]; |
874 | y = pl->y+freearr_y[i]; |
874 | y = pl->y+freearr_y[i]; |
875 | m = pl->map; |
875 | m = pl->map; |
876 | |
876 | |
877 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
877 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
878 | if (mflags & P_OUT_OF_MAP) continue; |
878 | if (mflags & P_OUT_OF_MAP) continue; |
879 | if (!(mflags & P_IS_ALIVE)) continue; |
879 | if (!(mflags & P_IS_ALIVE)) continue; |
880 | |
880 | |
881 | for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { |
881 | for(tmp=get_map_ob(m, x, y); tmp;tmp=tmp->above) { |
882 | if(QUERY_FLAG(tmp,FLAG_MONSTER)) break; |
882 | if(QUERY_FLAG(tmp,FLAG_MONSTER)) break; |
883 | /* can't affect players */ |
883 | /* can't affect players */ |
884 | if(tmp->type==PLAYER) break; |
884 | if(tmp->type==PLAYER) break; |
885 | } |
885 | } |
886 | |
886 | |
887 | /* Whole bunch of checks to see if this is a type of monster that would |
887 | /* Whole bunch of checks to see if this is a type of monster that would |
888 | * listen to singing. |
888 | * listen to singing. |
889 | */ |
889 | */ |
890 | if (tmp && QUERY_FLAG(tmp, FLAG_MONSTER) && |
890 | if (tmp && QUERY_FLAG(tmp, FLAG_MONSTER) && |
891 | !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 */ |
892 | !QUERY_FLAG(tmp, FLAG_SPLITTING) && /* no ears */ |
893 | !QUERY_FLAG(tmp, FLAG_HITBACK) && /* was here before */ |
893 | !QUERY_FLAG(tmp, FLAG_HITBACK) && /* was here before */ |
894 | (tmp->level <= skill->level) && |
894 | (tmp->level <= skill->level) && |
895 | (!tmp->head) && |
895 | (!tmp->head) && |
896 | !QUERY_FLAG(tmp, FLAG_UNDEAD) && |
896 | !QUERY_FLAG(tmp, FLAG_UNDEAD) && |
897 | !QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && /* already calm */ |
897 | !QUERY_FLAG(tmp,FLAG_UNAGGRESSIVE) && /* already calm */ |
898 | !QUERY_FLAG(tmp,FLAG_FRIENDLY)) { /* already calm */ |
898 | !QUERY_FLAG(tmp,FLAG_FRIENDLY)) { /* already calm */ |
899 | |
899 | |
900 | /* stealing isn't really related (although, maybe it should |
900 | /* stealing isn't really related (although, maybe it should |
901 | * be). This is mainly to prevent singing to the same monster |
901 | * be). This is mainly to prevent singing to the same monster |
902 | * over and over again and getting exp for it. |
902 | * over and over again and getting exp for it. |
903 | */ |
903 | */ |
904 | chance=skill->level*2+(pl->stats.Cha-5-tmp->stats.Int)/2; |
904 | 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)) { |
905 | if(chance && tmp->level*2<random_roll(0, chance-1, pl, PREFER_HIGH)) { |
906 | SET_FLAG(tmp,FLAG_UNAGGRESSIVE); |
906 | SET_FLAG(tmp,FLAG_UNAGGRESSIVE); |
907 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
907 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
908 | "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 */ |
909 | /* Give exp only if they are not aware */ |
910 | if(!QUERY_FLAG(tmp,FLAG_NO_STEAL)) |
910 | if(!QUERY_FLAG(tmp,FLAG_NO_STEAL)) |
911 | exp += calc_skill_exp(pl,tmp, skill); |
911 | exp += calc_skill_exp(pl,tmp, skill); |
912 | SET_FLAG(tmp,FLAG_NO_STEAL); |
912 | SET_FLAG(tmp,FLAG_NO_STEAL); |
913 | } else { |
913 | } else { |
914 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
914 | new_draw_info_format(NDI_UNIQUE, 0,pl, |
915 | "Too bad the %s isn't listening!\n",query_name(tmp)); |
915 | "Too bad the %s isn't listening!\n",query_name(tmp)); |
916 | SET_FLAG(tmp,FLAG_NO_STEAL); |
916 | SET_FLAG(tmp,FLAG_NO_STEAL); |
917 | } |
917 | } |
918 | } |
918 | } |
919 | } |
919 | } |
920 | return exp; |
920 | return exp; |
921 | } |
921 | } |
922 | |
922 | |
923 | /* The find_traps skill (aka, search). Checks for traps |
923 | /* The find_traps skill (aka, search). Checks for traps |
… | |
… | |
933 | /* First we search all around us for runes and traps, which are |
933 | /* First we search all around us for runes and traps, which are |
934 | * all type RUNE |
934 | * all type RUNE |
935 | */ |
935 | */ |
936 | |
936 | |
937 | for(i=0;i<9;i++) { |
937 | for(i=0;i<9;i++) { |
938 | x = pl->x+freearr_x[i]; |
938 | x = pl->x+freearr_x[i]; |
939 | y = pl->y+freearr_y[i]; |
939 | y = pl->y+freearr_y[i]; |
940 | m = pl->map; |
940 | m = pl->map; |
941 | |
941 | |
942 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
942 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
943 | if (mflags & P_OUT_OF_MAP) continue; |
943 | if (mflags & P_OUT_OF_MAP) continue; |
944 | |
944 | |
945 | /* Check everything in the square for trapness */ |
945 | /* Check everything in the square for trapness */ |
946 | for(tmp = get_map_ob(m, x, y); tmp!=NULL;tmp=tmp->above) { |
946 | for(tmp = get_map_ob(m, x, y); tmp!=NULL;tmp=tmp->above) { |
947 | |
947 | |
948 | /* And now we'd better do an inventory traversal of each |
948 | /* And now we'd better do an inventory traversal of each |
949 | * of these objects' inventory |
949 | * of these objects' inventory |
950 | * We can narrow this down a bit - no reason to search through |
950 | * We can narrow this down a bit - no reason to search through |
951 | * the players inventory or monsters for that matter. |
951 | * the players inventory or monsters for that matter. |
952 | */ |
952 | */ |
953 | if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) { |
953 | if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) { |
954 | for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) |
954 | for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) |
955 | if(tmp2->type==RUNE || tmp2->type == TRAP) |
955 | if(tmp2->type==RUNE || tmp2->type == TRAP) |
956 | if(trap_see(pl,tmp2)) { |
956 | if(trap_see(pl,tmp2)) { |
957 | trap_show(tmp2,tmp); |
957 | trap_show(tmp2,tmp); |
958 | if(tmp2->stats.Cha>1) { |
958 | if(tmp2->stats.Cha>1) { |
959 | if (!tmp2->owner || tmp2->owner->type!=PLAYER) |
959 | if (!tmp2->owner || tmp2->owner->type!=PLAYER) |
960 | expsum += calc_skill_exp(pl,tmp2, skill); |
960 | expsum += calc_skill_exp(pl,tmp2, skill); |
961 | |
961 | |
962 | tmp2->stats.Cha = 1; /* unhide the trap */ |
962 | tmp2->stats.Cha = 1; /* unhide the trap */ |
963 | } |
963 | } |
964 | } |
964 | } |
965 | } |
965 | } |
966 | if((tmp->type==RUNE || tmp->type == TRAP) && trap_see(pl,tmp)) { |
966 | if((tmp->type==RUNE || tmp->type == TRAP) && trap_see(pl,tmp)) { |
967 | trap_show(tmp,tmp); |
967 | trap_show(tmp,tmp); |
968 | if(tmp->stats.Cha>1) { |
968 | if(tmp->stats.Cha>1) { |
969 | if (!tmp->owner || tmp->owner->type!=PLAYER) |
969 | if (!tmp->owner || tmp->owner->type!=PLAYER) |
970 | expsum += calc_skill_exp(pl,tmp, skill); |
970 | expsum += calc_skill_exp(pl,tmp, skill); |
971 | tmp->stats.Cha = 1; /* unhide the trap */ |
971 | tmp->stats.Cha = 1; /* unhide the trap */ |
972 | } |
972 | } |
973 | } |
973 | } |
974 | } |
974 | } |
975 | } |
975 | } |
976 | new_draw_info(NDI_BLACK, 0, pl, "You search the area."); |
976 | new_draw_info(NDI_BLACK, 0, pl, "You search the area."); |
977 | return expsum; |
977 | return expsum; |
978 | } |
978 | } |
979 | |
979 | |
… | |
… | |
986 | int i,success=0,mflags; |
986 | int i,success=0,mflags; |
987 | mapstruct *m; |
987 | mapstruct *m; |
988 | sint16 x,y; |
988 | sint16 x,y; |
989 | |
989 | |
990 | for(i=0;i<9;i++) { |
990 | for(i=0;i<9;i++) { |
991 | x = op->x + freearr_x[i]; |
991 | x = op->x + freearr_x[i]; |
992 | y = op->y + freearr_y[i]; |
992 | y = op->y + freearr_y[i]; |
993 | m = op->map; |
993 | m = op->map; |
994 | |
994 | |
995 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
995 | mflags =get_map_flags(m, &m, x,y, &x, &y); |
996 | if (mflags & P_OUT_OF_MAP) continue; |
996 | if (mflags & P_OUT_OF_MAP) continue; |
997 | |
997 | |
998 | /* Check everything in the square for trapness */ |
998 | /* Check everything in the square for trapness */ |
999 | for(tmp = get_map_ob(m,x,y);tmp!=NULL;tmp=tmp->above) { |
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 |
1000 | /* And now we'd better do an inventory traversal of each |
1001 | * of these objects inventory. Like above, only |
1001 | * of these objects inventory. Like above, only |
1002 | * do this for interesting objects. |
1002 | * do this for interesting objects. |
1003 | */ |
1003 | */ |
1004 | |
1004 | |
1005 | if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) { |
1005 | if (tmp->type != PLAYER && !QUERY_FLAG(tmp, FLAG_MONSTER)) { |
1006 | for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) |
1006 | for(tmp2=tmp->inv;tmp2!=NULL;tmp2=tmp2->below) |
1007 | if((tmp2->type==RUNE || tmp2->type == TRAP) && tmp2->stats.Cha<=1) { |
1007 | if((tmp2->type==RUNE || tmp2->type == TRAP) && tmp2->stats.Cha<=1) { |
1008 | trap_show(tmp2,tmp); |
1008 | trap_show(tmp2,tmp); |
1009 | if(trap_disarm(op,tmp2,1, skill) && (!tmp2->owner || tmp2->owner->type!=PLAYER)) { |
1009 | if(trap_disarm(op,tmp2,1, skill) && (!tmp2->owner || tmp2->owner->type!=PLAYER)) { |
1010 | tmp->stats.exp = tmp->stats.Cha * tmp->level; |
1010 | tmp->stats.exp = tmp->stats.Cha * tmp->level; |
1011 | success += calc_skill_exp(op,tmp2, skill); |
1011 | success += calc_skill_exp(op,tmp2, skill); |
1012 | } |
1012 | } |
1013 | } |
1013 | } |
1014 | } |
1014 | } |
1015 | if((tmp->type==RUNE || tmp->type==TRAP) && tmp->stats.Cha<=1) { |
1015 | if((tmp->type==RUNE || tmp->type==TRAP) && tmp->stats.Cha<=1) { |
1016 | trap_show(tmp,tmp); |
1016 | trap_show(tmp,tmp); |
1017 | if (trap_disarm(op,tmp,1,skill) && (!tmp->owner || tmp->owner->type!=PLAYER)) { |
1017 | if (trap_disarm(op,tmp,1,skill) && (!tmp->owner || tmp->owner->type!=PLAYER)) { |
1018 | tmp->stats.exp = tmp->stats.Cha * tmp->level; |
1018 | tmp->stats.exp = tmp->stats.Cha * tmp->level; |
1019 | success += calc_skill_exp(op,tmp,skill); |
1019 | success += calc_skill_exp(op,tmp,skill); |
1020 | } |
1020 | } |
1021 | } |
1021 | } |
1022 | } |
1022 | } |
1023 | } |
1023 | } |
1024 | return success; |
1024 | return success; |
1025 | } |
1025 | } |
1026 | |
1026 | |
1027 | |
1027 | |
… | |
… | |
1045 | * but if someone buries an altar, I don't see a problem with |
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 |
1046 | * going through all the objects, and it shouldn't be much slower |
1047 | * than extra checks on object attributes. |
1047 | * than extra checks on object attributes. |
1048 | */ |
1048 | */ |
1049 | for (tmp=pl->below; tmp!=NULL; tmp=tmp->below) { |
1049 | for (tmp=pl->below; tmp!=NULL; tmp=tmp->below) { |
1050 | /* Only if the altar actually belongs to someone do you get special benefits */ |
1050 | /* Only if the altar actually belongs to someone do you get special benefits */ |
1051 | if(tmp && tmp->type==HOLY_ALTAR && tmp->other_arch) { |
1051 | if(tmp && tmp->type==HOLY_ALTAR && tmp->other_arch) { |
1052 | sprintf(buf,"You pray over the %s.",tmp->name); |
1052 | sprintf(buf,"You pray over the %s.",tmp->name); |
1053 | pray_at_altar(pl,tmp, skill); |
1053 | pray_at_altar(pl,tmp, skill); |
1054 | break; /* Only pray at one altar */ |
1054 | break; /* Only pray at one altar */ |
1055 | } |
1055 | } |
1056 | } |
1056 | } |
1057 | |
1057 | |
1058 | new_draw_info(NDI_BLACK,0,pl,buf); |
1058 | new_draw_info(NDI_BLACK,0,pl,buf); |
1059 | |
1059 | |
1060 | if(pl->stats.grace < pl->stats.maxgrace) { |
1060 | if(pl->stats.grace < pl->stats.maxgrace) { |
1061 | pl->stats.grace++; |
1061 | pl->stats.grace++; |
1062 | pl->last_grace = -1; |
1062 | pl->last_grace = -1; |
1063 | } |
1063 | } |
1064 | return 0; |
1064 | return 0; |
1065 | } |
1065 | } |
1066 | |
1066 | |
1067 | /* This skill allows the player to regain a few sp or hp for a |
1067 | /* This skill allows the player to regain a few sp or hp for a |
… | |
… | |
1077 | if(pl->type!=PLAYER) return; /* players only */ |
1077 | if(pl->type!=PLAYER) return; /* players only */ |
1078 | |
1078 | |
1079 | /* check if pl has removed encumbering armour and weapons */ |
1079 | /* check if pl has removed encumbering armour and weapons */ |
1080 | if(QUERY_FLAG(pl,FLAG_READY_WEAPON) && (skill->level<6)) { |
1080 | if(QUERY_FLAG(pl,FLAG_READY_WEAPON) && (skill->level<6)) { |
1081 | new_draw_info(NDI_UNIQUE,0,pl, |
1081 | new_draw_info(NDI_UNIQUE,0,pl, |
1082 | "You can't concentrate while wielding a weapon!\n"); |
1082 | "You can't concentrate while wielding a weapon!\n"); |
1083 | return; |
1083 | return; |
1084 | } else { |
1084 | } else { |
1085 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
1085 | for(tmp=pl->inv;tmp;tmp=tmp->below) |
1086 | if (( (tmp->type==ARMOUR && skill->level<12) |
1086 | if (( (tmp->type==ARMOUR && skill->level<12) |
1087 | || (tmp->type==HELMET && skill->level<10) |
1087 | || (tmp->type==HELMET && skill->level<10) |
1088 | || (tmp->type==SHIELD && skill->level<6) |
1088 | || (tmp->type==SHIELD && skill->level<6) |
1089 | || (tmp->type==BOOTS && skill->level<4) |
1089 | || (tmp->type==BOOTS && skill->level<4) |
1090 | || (tmp->type==GLOVES && skill->level<2) ) |
1090 | || (tmp->type==GLOVES && skill->level<2) ) |
1091 | && QUERY_FLAG(tmp,FLAG_APPLIED)) { |
1091 | && QUERY_FLAG(tmp,FLAG_APPLIED)) { |
1092 | new_draw_info(NDI_UNIQUE,0,pl, |
1092 | new_draw_info(NDI_UNIQUE,0,pl, |
1093 | "You can't concentrate while wearing so much armour!\n"); |
1093 | "You can't concentrate while wearing so much armour!\n"); |
1094 | return; |
1094 | return; |
1095 | } |
1095 | } |
1096 | } |
1096 | } |
1097 | |
1097 | |
1098 | /* ok let's meditate! Spell points are regained first, then once |
1098 | /* ok let's meditate! Spell points are regained first, then once |
1099 | * they are maxed we get back hp. Actual incrementing of values |
1099 | * 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 |
1100 | * is handled by the do_some_living() (in player.c). This way magical |
… | |
… | |
1104 | */ |
1104 | */ |
1105 | |
1105 | |
1106 | new_draw_info(NDI_BLACK,0,pl, "You meditate."); |
1106 | new_draw_info(NDI_BLACK,0,pl, "You meditate."); |
1107 | |
1107 | |
1108 | if(pl->stats.sp < pl->stats.maxsp) { |
1108 | if(pl->stats.sp < pl->stats.maxsp) { |
1109 | pl->stats.sp++; |
1109 | pl->stats.sp++; |
1110 | pl->last_sp = -1; |
1110 | pl->last_sp = -1; |
1111 | } else if (pl->stats.hp < pl->stats.maxhp) { |
1111 | } else if (pl->stats.hp < pl->stats.maxhp) { |
1112 | pl->stats.hp++; |
1112 | pl->stats.hp++; |
1113 | pl->last_heal = -1; |
1113 | pl->last_heal = -1; |
1114 | } |
1114 | } |
1115 | } |
1115 | } |
1116 | |
1116 | |
1117 | /* write_note() - this routine allows players to inscribe messages in |
1117 | /* write_note() - this routine allows players to inscribe messages in |
1118 | * ordinary 'books' (anything that is type BOOK). b.t. |
1118 | * ordinary 'books' (anything that is type BOOK). b.t. |
… | |
… | |
1124 | |
1124 | |
1125 | /* a pair of sanity checks */ |
1125 | /* a pair of sanity checks */ |
1126 | if(!item||item->type!=BOOK) return 0; |
1126 | if(!item||item->type!=BOOK) return 0; |
1127 | |
1127 | |
1128 | if(!msg) { |
1128 | if(!msg) { |
1129 | new_draw_info(NDI_UNIQUE,0,pl,"No message to write!"); |
1129 | 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>", |
1130 | new_draw_info_format(NDI_UNIQUE,0,pl,"Usage: use_skill %s <message>", |
1131 | skill->skill); |
1131 | skill->skill); |
1132 | return 0; |
1132 | return 0; |
1133 | } |
1133 | } |
1134 | if (strcasestr_local(msg, "endmsg")) { |
1134 | if (strcasestr_local(msg, "endmsg")) { |
1135 | new_draw_info(NDI_UNIQUE,0,pl,"Trying to cheat now are we?"); |
1135 | new_draw_info(NDI_UNIQUE,0,pl,"Trying to cheat now are we?"); |
1136 | return 0; |
1136 | return 0; |
1137 | } |
1137 | } |
1138 | |
1138 | |
1139 | if (INVOKE_OBJECT (INSCRIBE_NOTE, item, ARG_PLAYER (pl->contr), ARG_STRING (msg), ARG_OBJECT (skill))) |
1139 | if (INVOKE_OBJECT (INSCRIBE_NOTE, item, ARG_PLAYER (pl->contr), ARG_STRING (msg), ARG_OBJECT (skill))) |
1140 | return strlen (msg); |
1140 | return strlen (msg); |
1141 | |
1141 | |
1142 | buf[0] = 0; |
1142 | buf[0] = 0; |
1143 | if(!book_overflow(item->msg,msg,sizeof (buf))) { /* add msg string to book */ |
1143 | if(!book_overflow(item->msg,msg,sizeof (buf))) { /* add msg string to book */ |
1144 | if(item->msg) |
1144 | if(item->msg) |
1145 | strcpy(buf,item->msg); |
1145 | strcpy(buf,item->msg); |
1146 | |
1146 | |
1147 | strcat(buf,msg); |
1147 | strcat(buf,msg); |
1148 | strcat(buf,"\n"); /* new msg needs a LF */ |
1148 | strcat(buf,"\n"); /* new msg needs a LF */ |
1149 | if(item->nrof > 1) { |
1149 | if(item->nrof > 1) { |
1150 | newBook = get_object(); |
1150 | newBook = get_object(); |
1151 | copy_object(item, newBook); |
1151 | copy_object(item, newBook); |
1152 | decrease_ob(item); |
1152 | decrease_ob(item); |
1153 | esrv_send_item(pl, item); |
1153 | esrv_send_item(pl, item); |
1154 | newBook->nrof = 1; |
1154 | newBook->nrof = 1; |
1155 | if (newBook->msg) free_string(newBook->msg); |
1155 | if (newBook->msg) free_string(newBook->msg); |
1156 | newBook->msg = add_string(buf); |
1156 | newBook->msg = add_string(buf); |
1157 | newBook = insert_ob_in_ob(newBook, pl); |
1157 | newBook = insert_ob_in_ob(newBook, pl); |
1158 | esrv_send_item(pl, newBook); |
1158 | esrv_send_item(pl, newBook); |
1159 | } else { |
1159 | } else { |
1160 | if (item->msg) free_string(item->msg); |
1160 | if (item->msg) free_string(item->msg); |
1161 | item->msg=add_string(buf); |
1161 | item->msg=add_string(buf); |
1162 | /* This shouldn't be necessary - the object hasn't changed in any |
1162 | /* This shouldn't be necessary - the object hasn't changed in any |
1163 | * visible way |
1163 | * visible way |
1164 | */ |
1164 | */ |
1165 | /* esrv_send_item(pl, item);*/ |
1165 | /* esrv_send_item(pl, item);*/ |
1166 | } |
1166 | } |
1167 | new_draw_info_format(NDI_UNIQUE,0,pl, "You write in the %s.", |
1167 | new_draw_info_format(NDI_UNIQUE,0,pl, "You write in the %s.", |
1168 | query_short_name(item)); |
1168 | query_short_name(item)); |
1169 | return strlen(msg); |
1169 | return strlen(msg); |
1170 | } else |
1170 | } else |
1171 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1171 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1172 | "Your message won't fit in the %s!", |
1172 | "Your message won't fit in the %s!", |
1173 | query_short_name(item)); |
1173 | query_short_name(item)); |
1174 | |
1174 | |
… | |
… | |
1185 | int success=0,confused=0; |
1185 | int success=0,confused=0; |
1186 | object *newscroll, *chosen_spell, *tmp; |
1186 | object *newscroll, *chosen_spell, *tmp; |
1187 | |
1187 | |
1188 | /* this is a sanity check */ |
1188 | /* this is a sanity check */ |
1189 | if (scroll->type!=SCROLL) { |
1189 | if (scroll->type!=SCROLL) { |
1190 | new_draw_info(NDI_UNIQUE,0,pl,"A spell can only be inscribed into a scroll!"); |
1190 | new_draw_info(NDI_UNIQUE,0,pl,"A spell can only be inscribed into a scroll!"); |
1191 | return 0; |
1191 | return 0; |
1192 | } |
1192 | } |
1193 | |
1193 | |
1194 | /* Check if we are ready to attempt inscription */ |
1194 | /* Check if we are ready to attempt inscription */ |
1195 | chosen_spell=pl->contr->ranges[range_magic]; |
1195 | chosen_spell=pl->contr->ranges[range_magic]; |
1196 | if(!chosen_spell) { |
1196 | if(!chosen_spell) { |
1197 | new_draw_info(NDI_UNIQUE,0,pl, |
1197 | new_draw_info(NDI_UNIQUE,0,pl, |
1198 | "You need a spell readied in order to inscribe!"); |
1198 | "You need a spell readied in order to inscribe!"); |
1199 | return 0; |
1199 | return 0; |
1200 | } |
1200 | } |
1201 | if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE) > pl->stats.grace) { |
1201 | if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE) > pl->stats.grace) { |
1202 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1202 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1203 | "You don't have enough grace to write a scroll of %s.", |
1203 | "You don't have enough grace to write a scroll of %s.", |
1204 | chosen_spell->name); |
1204 | chosen_spell->name); |
1205 | return 0; |
1205 | return 0; |
1206 | } |
1206 | } |
1207 | if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA) > pl->stats.sp) { |
1207 | if(SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA) > pl->stats.sp) { |
1208 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1208 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1209 | "You don't have enough mana to write a scroll of %s.", |
1209 | "You don't have enough mana to write a scroll of %s.", |
1210 | chosen_spell->name); |
1210 | chosen_spell->name); |
1211 | return 0; |
1211 | return 0; |
1212 | } |
1212 | } |
1213 | |
1213 | |
1214 | /* if there is a spell already on the scroll then player could easily |
1214 | /* if there is a spell already on the scroll then player could easily |
1215 | * accidently read it while trying to write the new one. give player |
1215 | * accidently read it while trying to write the new one. give player |
1216 | * a 50% chance to overwrite spell at their own level |
1216 | * a 50% chance to overwrite spell at their own level |
1217 | */ |
1217 | */ |
1218 | if((scroll->stats.sp || scroll->inv) && |
1218 | if((scroll->stats.sp || scroll->inv) && |
1219 | random_roll(0, scroll->level*2, pl, PREFER_LOW)>skill->level) { |
1219 | random_roll(0, scroll->level*2, pl, PREFER_LOW)>skill->level) { |
1220 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1220 | new_draw_info_format(NDI_UNIQUE,0,pl, |
1221 | "Oops! You accidently read it while trying to write on it."); |
1221 | "Oops! You accidently read it while trying to write on it."); |
1222 | manual_apply(pl,scroll,0); |
1222 | manual_apply(pl,scroll,0); |
1223 | return 0; |
1223 | return 0; |
1224 | } |
1224 | } |
1225 | |
1225 | |
1226 | /* ok, we are ready to try inscription */ |
1226 | /* ok, we are ready to try inscription */ |
1227 | if(QUERY_FLAG(pl,FLAG_CONFUSED)) confused = 1; |
1227 | if(QUERY_FLAG(pl,FLAG_CONFUSED)) confused = 1; |
1228 | |
1228 | |
1229 | /* Lost mana/grace no matter what */ |
1229 | /* Lost mana/grace no matter what */ |
1230 | pl->stats.grace-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE); |
1230 | pl->stats.grace-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_GRACE); |
1231 | pl->stats.sp-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA); |
1231 | pl->stats.sp-=SP_level_spellpoint_cost(pl,chosen_spell,SPELL_MANA); |
1232 | |
1232 | |
1233 | if (random_roll(0, chosen_spell->level*4-1, pl, PREFER_LOW) < skill->level) { |
1233 | if (random_roll(0, chosen_spell->level*4-1, pl, PREFER_LOW) < skill->level) { |
1234 | if (scroll->nrof > 1) { |
1234 | if (scroll->nrof > 1) { |
1235 | newscroll = get_object(); |
1235 | newscroll = get_object(); |
1236 | copy_object(scroll, newscroll); |
1236 | copy_object(scroll, newscroll); |
1237 | decrease_ob(scroll); |
1237 | decrease_ob(scroll); |
1238 | newscroll->nrof = 1; |
1238 | newscroll->nrof = 1; |
1239 | } else { |
1239 | } else { |
1240 | newscroll = scroll; |
1240 | newscroll = scroll; |
1241 | } |
1241 | } |
1242 | |
1242 | |
1243 | if(!confused) { |
1243 | if(!confused) { |
1244 | newscroll->level= MAX(skill->level, chosen_spell->level); |
1244 | newscroll->level= MAX(skill->level, chosen_spell->level); |
1245 | new_draw_info(NDI_UNIQUE,0,pl, |
1245 | new_draw_info(NDI_UNIQUE,0,pl, |
1246 | "You succeed in writing a new scroll."); |
1246 | "You succeed in writing a new scroll."); |
1247 | } else { |
1247 | } else { |
1248 | chosen_spell = find_random_spell_in_ob(pl, NULL); |
1248 | chosen_spell = find_random_spell_in_ob(pl, NULL); |
1249 | if (!chosen_spell) return 0; |
1249 | if (!chosen_spell) return 0; |
1250 | |
1250 | |
1251 | newscroll->level= MAX(skill->level, chosen_spell->level); |
1251 | newscroll->level= MAX(skill->level, chosen_spell->level); |
1252 | new_draw_info(NDI_UNIQUE,0,pl, |
1252 | new_draw_info(NDI_UNIQUE,0,pl, |
1253 | "In your confused state, you write down some odd spell."); |
1253 | "In your confused state, you write down some odd spell."); |
1254 | } |
1254 | } |
1255 | |
1255 | |
1256 | if (newscroll->inv) { |
1256 | if (newscroll->inv) { |
1257 | object *ninv; |
1257 | object *ninv; |
1258 | |
1258 | |
1259 | ninv = newscroll->inv; |
1259 | ninv = newscroll->inv; |
1260 | remove_ob(ninv); |
1260 | remove_ob(ninv); |
1261 | free_object(ninv); |
1261 | free_object(ninv); |
1262 | } |
1262 | } |
1263 | tmp = get_object(); |
1263 | tmp = get_object(); |
1264 | copy_object(chosen_spell, tmp); |
1264 | copy_object(chosen_spell, tmp); |
1265 | insert_ob_in_ob(tmp, newscroll); |
1265 | insert_ob_in_ob(tmp, newscroll); |
1266 | |
1266 | |
1267 | /* Same code as from treasure.c - so they can better merge. |
1267 | /* Same code as from treasure.c - so they can better merge. |
1268 | * if players want to sell them, so be it. |
1268 | * if players want to sell them, so be it. |
1269 | */ |
1269 | */ |
1270 | newscroll->value = newscroll->arch->clone.value * newscroll->inv->value * |
1270 | newscroll->value = newscroll->arch->clone.value * newscroll->inv->value * |
1271 | (newscroll->level +50) / (newscroll->inv->level + 50); |
1271 | (newscroll->level +50) / (newscroll->inv->level + 50); |
1272 | newscroll->stats.exp = newscroll->value/5; |
1272 | newscroll->stats.exp = newscroll->value/5; |
1273 | |
1273 | |
1274 | /* wait until finished manipulating the scroll before inserting it */ |
1274 | /* wait until finished manipulating the scroll before inserting it */ |
1275 | if (newscroll == scroll) |
1275 | if (newscroll == scroll) |
1276 | { |
1276 | { |
1277 | /* Remove to correctly merge with other items which may exist in inventory */ |
1277 | /* Remove to correctly merge with other items which may exist in inventory */ |
1278 | remove_ob(newscroll); |
1278 | remove_ob(newscroll); |
1279 | esrv_del_item(pl->contr,newscroll->count); |
1279 | esrv_del_item(pl->contr,newscroll->count); |
1280 | } |
1280 | } |
1281 | newscroll=insert_ob_in_ob(newscroll,pl); |
1281 | newscroll=insert_ob_in_ob(newscroll,pl); |
1282 | esrv_send_item(pl, newscroll); |
1282 | esrv_send_item(pl, newscroll); |
1283 | success = calc_skill_exp(pl,newscroll, skill); |
1283 | success = calc_skill_exp(pl,newscroll, skill); |
1284 | if(!confused) success *= 2; |
1284 | if(!confused) success *= 2; |
1285 | success = success * skill->level; |
1285 | success = success * skill->level; |
1286 | return success; |
1286 | return success; |
1287 | |
1287 | |
1288 | } else { /* Inscription has failed */ |
1288 | } else { /* Inscription has failed */ |
1289 | |
1289 | |
1290 | if(chosen_spell->level>skill->level || confused) { /*backfire!*/ |
1290 | if(chosen_spell->level>skill->level || confused) { /*backfire!*/ |
1291 | new_draw_info(NDI_UNIQUE,0,pl, |
1291 | new_draw_info(NDI_UNIQUE,0,pl, |
1292 | "Ouch! Your attempt to write a new scroll strains your mind!"); |
1292 | "Ouch! Your attempt to write a new scroll strains your mind!"); |
1293 | if(random_roll(0, 1, pl, PREFER_LOW)==1) |
1293 | if(random_roll(0, 1, pl, PREFER_LOW)==1) |
1294 | drain_specific_stat(pl,4); |
1294 | drain_specific_stat(pl,4); |
1295 | else { |
1295 | else { |
1296 | confuse_player(pl,pl,99); |
1296 | confuse_player(pl,pl,99); |
1297 | return (-30*chosen_spell->level); |
1297 | return (-30*chosen_spell->level); |
1298 | } |
1298 | } |
1299 | } else if(random_roll(0, pl->stats.Int-1, pl, PREFER_HIGH) < 15) { |
1299 | } else if(random_roll(0, pl->stats.Int-1, pl, PREFER_HIGH) < 15) { |
1300 | new_draw_info(NDI_UNIQUE,0,pl, |
1300 | new_draw_info(NDI_UNIQUE,0,pl, |
1301 | "Your attempt to write a new scroll rattles your mind!"); |
1301 | "Your attempt to write a new scroll rattles your mind!"); |
1302 | confuse_player(pl,pl,99); |
1302 | confuse_player(pl,pl,99); |
1303 | } else |
1303 | } else |
1304 | new_draw_info(NDI_UNIQUE,0,pl,"You fail to write a new scroll."); |
1304 | new_draw_info(NDI_UNIQUE,0,pl,"You fail to write a new scroll."); |
1305 | } |
1305 | } |
1306 | return 0; |
1306 | return 0; |
1307 | } |
1307 | } |
1308 | |
1308 | |
1309 | /* write_on_item() - wrapper for write_note and write_scroll */ |
1309 | /* write_on_item() - wrapper for write_note and write_scroll */ |
… | |
… | |
1314 | archetype *skat; |
1314 | archetype *skat; |
1315 | |
1315 | |
1316 | if(pl->type!=PLAYER) return 0; |
1316 | if(pl->type!=PLAYER) return 0; |
1317 | |
1317 | |
1318 | if (!params) { |
1318 | if (!params) { |
1319 | params=""; |
1319 | params=""; |
1320 | string=params; |
1320 | string=params; |
1321 | } |
1321 | } |
1322 | skat = get_archetype_by_type_subtype(SKILL, SK_LITERACY); |
1322 | skat = get_archetype_by_type_subtype(SKILL, SK_LITERACY); |
1323 | |
1323 | |
1324 | /* Need to be able to read before we can write! */ |
1324 | /* Need to be able to read before we can write! */ |
1325 | if(!find_skill_by_name(pl,skat->clone.skill)) { |
1325 | if(!find_skill_by_name(pl,skat->clone.skill)) { |
1326 | new_draw_info(NDI_UNIQUE,0,pl, |
1326 | new_draw_info(NDI_UNIQUE,0,pl, |
1327 | "You must learn to read before you can write!"); |
1327 | "You must learn to read before you can write!"); |
1328 | return 0; |
1328 | return 0; |
1329 | } |
1329 | } |
1330 | |
1330 | |
1331 | /* if there is a message then it goes in a book and no message means |
1331 | /* if there is a message then it goes in a book and no message means |
1332 | * write active spell into the scroll |
1332 | * write active spell into the scroll |
1333 | */ |
1333 | */ |
1334 | msgtype = (string[0]!='\0') ? BOOK : SCROLL; |
1334 | msgtype = (string[0]!='\0') ? BOOK : SCROLL; |
1335 | |
1335 | |
1336 | /* find an item of correct type to write on */ |
1336 | /* find an item of correct type to write on */ |
1337 | if ( !(item = find_marked_object(pl))){ |
1337 | if ( !(item = find_marked_object(pl))){ |
1338 | new_draw_info(NDI_UNIQUE,0,pl,"You don't have any marked item to write on."); |
1338 | new_draw_info(NDI_UNIQUE,0,pl,"You don't have any marked item to write on."); |
1339 | return 0; |
1339 | return 0; |
1340 | } |
1340 | } |
1341 | |
1341 | |
1342 | if(QUERY_FLAG(item,FLAG_UNPAID)) { |
1342 | if(QUERY_FLAG(item,FLAG_UNPAID)) { |
1343 | new_draw_info(NDI_UNIQUE,0,pl, |
1343 | new_draw_info(NDI_UNIQUE,0,pl, |
1344 | "You had better pay for that before you write on it."); |
1344 | "You had better pay for that before you write on it."); |
1345 | return 0; |
1345 | return 0; |
1346 | } |
1346 | } |
1347 | if (msgtype != item->type) { |
1347 | if (msgtype != item->type) { |
1348 | new_draw_info_format(NDI_UNIQUE,0,pl,"You have no %s to write on", |
1348 | new_draw_info_format(NDI_UNIQUE,0,pl,"You have no %s to write on", |
1349 | msgtype==BOOK ? "book" : "scroll"); |
1349 | msgtype==BOOK ? "book" : "scroll"); |
1350 | return 0; |
1350 | return 0; |
1351 | } |
1351 | } |
1352 | |
1352 | |
1353 | if (msgtype == SCROLL) { |
1353 | if (msgtype == SCROLL) { |
1354 | return write_scroll(pl,item, skill); |
1354 | return write_scroll(pl,item, skill); |
1355 | } else if (msgtype == BOOK) { |
1355 | } else if (msgtype == BOOK) { |
1356 | return write_note(pl,item,string, skill); |
1356 | return write_note(pl,item,string, skill); |
1357 | } |
1357 | } |
1358 | return 0; |
1358 | return 0; |
1359 | } |
1359 | } |
1360 | |
1360 | |
1361 | |
1361 | |
… | |
… | |
1371 | |
1371 | |
1372 | static object *find_throw_ob( object *op, const char *request ) { |
1372 | static object *find_throw_ob( object *op, const char *request ) { |
1373 | object *tmp; |
1373 | object *tmp; |
1374 | |
1374 | |
1375 | if(!op) { /* safety */ |
1375 | if(!op) { /* safety */ |
1376 | LOG(llevError,"find_throw_ob(): confused! have a NULL thrower!\n"); |
1376 | LOG(llevError,"find_throw_ob(): confused! have a NULL thrower!\n"); |
1377 | return (object *) NULL; |
1377 | return (object *) NULL; |
1378 | } |
1378 | } |
1379 | |
1379 | |
1380 | /* prefer marked item */ |
1380 | /* prefer marked item */ |
1381 | tmp = find_marked_object(op); |
1381 | tmp = find_marked_object(op); |
1382 | if (tmp != NULL) { |
1382 | if (tmp != NULL) { |
… | |
… | |
1404 | * can be thrown from 'hand'. |
1404 | * can be thrown from 'hand'. |
1405 | */ |
1405 | */ |
1406 | if (!tmp) return NULL; |
1406 | if (!tmp) return NULL; |
1407 | |
1407 | |
1408 | if (QUERY_FLAG(tmp,FLAG_APPLIED)) { |
1408 | if (QUERY_FLAG(tmp,FLAG_APPLIED)) { |
1409 | if(tmp->type!=WEAPON) { |
1409 | if(tmp->type!=WEAPON) { |
1410 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1410 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1411 | "You can't throw %s.",query_name(tmp)); |
1411 | "You can't throw %s.",query_name(tmp)); |
1412 | tmp = NULL; |
1412 | tmp = NULL; |
1413 | } else if (QUERY_FLAG(tmp,FLAG_CURSED)||QUERY_FLAG(tmp,FLAG_DAMNED)) { |
1413 | } else if (QUERY_FLAG(tmp,FLAG_CURSED)||QUERY_FLAG(tmp,FLAG_DAMNED)) { |
1414 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1414 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1415 | "The %s sticks to your hand!",query_name(tmp)); |
1415 | "The %s sticks to your hand!",query_name(tmp)); |
1416 | tmp = NULL; |
1416 | tmp = NULL; |
1417 | } else { |
1417 | } else { |
1418 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) { |
1418 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) { |
1419 | LOG (llevError, "BUG: find_throw_ob(): couldn't unapply\n"); |
1419 | LOG (llevError, "BUG: find_throw_ob(): couldn't unapply\n"); |
1420 | tmp = NULL; |
1420 | tmp = NULL; |
1421 | } |
1421 | } |
1422 | } |
1422 | } |
1423 | } else if (QUERY_FLAG(tmp, FLAG_UNPAID)) { |
1423 | } else if (QUERY_FLAG(tmp, FLAG_UNPAID)) { |
1424 | new_draw_info_format(NDI_UNIQUE, 0, op, "You should pay for the %s first.", query_name(tmp)); |
1424 | new_draw_info_format(NDI_UNIQUE, 0, op, "You should pay for the %s first.", query_name(tmp)); |
1425 | tmp = NULL; |
1425 | tmp = NULL; |
1426 | } |
1426 | } |
1427 | |
1427 | |
1428 | if (tmp && QUERY_FLAG (tmp, FLAG_INV_LOCKED)) { |
1428 | if (tmp && QUERY_FLAG (tmp, FLAG_INV_LOCKED)) { |
1429 | LOG (llevError, "BUG: find_throw_ob(): object is locked\n"); |
1429 | LOG (llevError, "BUG: find_throw_ob(): object is locked\n"); |
1430 | tmp=NULL; |
1430 | tmp=NULL; |
1431 | } |
1431 | } |
1432 | return tmp; |
1432 | return tmp; |
1433 | } |
1433 | } |
1434 | |
1434 | |
1435 | /* make_throw_ob() We construct the 'carrier' object in |
1435 | /* make_throw_ob() We construct the 'carrier' object in |
… | |
… | |
1442 | |
1442 | |
1443 | if(!orig) return NULL; |
1443 | if(!orig) return NULL; |
1444 | |
1444 | |
1445 | toss_item=get_object(); |
1445 | toss_item=get_object(); |
1446 | if (QUERY_FLAG (orig, FLAG_APPLIED)) { |
1446 | if (QUERY_FLAG (orig, FLAG_APPLIED)) { |
1447 | LOG (llevError, "BUG: make_throw_ob(): ob is applied\n"); |
1447 | LOG (llevError, "BUG: make_throw_ob(): ob is applied\n"); |
1448 | /* insufficient workaround, but better than nothing */ |
1448 | /* insufficient workaround, but better than nothing */ |
1449 | CLEAR_FLAG (orig, FLAG_APPLIED); |
1449 | CLEAR_FLAG (orig, FLAG_APPLIED); |
1450 | } |
1450 | } |
1451 | copy_object(orig,toss_item); |
1451 | copy_object(orig,toss_item); |
1452 | toss_item->type = THROWN_OBJ; |
1452 | toss_item->type = THROWN_OBJ; |
1453 | CLEAR_FLAG(toss_item,FLAG_CHANGING); |
1453 | CLEAR_FLAG(toss_item,FLAG_CHANGING); |
1454 | toss_item->stats.dam = 0; /* default damage */ |
1454 | toss_item->stats.dam = 0; /* default damage */ |
… | |
… | |
1471 | mapstruct *m; |
1471 | mapstruct *m; |
1472 | sint16 sx, sy; |
1472 | sint16 sx, sy; |
1473 | tag_t tag; |
1473 | tag_t tag; |
1474 | |
1474 | |
1475 | if(throw_ob==NULL) { |
1475 | if(throw_ob==NULL) { |
1476 | if(op->type==PLAYER) { |
1476 | if(op->type==PLAYER) { |
1477 | new_draw_info(NDI_UNIQUE, 0,op,"You have nothing to throw."); |
1477 | new_draw_info(NDI_UNIQUE, 0,op,"You have nothing to throw."); |
1478 | } |
1478 | } |
1479 | return 0; |
1479 | return 0; |
1480 | } |
1480 | } |
1481 | if (QUERY_FLAG(throw_ob, FLAG_STARTEQUIP)) { |
1481 | if (QUERY_FLAG(throw_ob, FLAG_STARTEQUIP)) { |
1482 | if (op->type==PLAYER) { |
1482 | if (op->type==PLAYER) { |
1483 | new_draw_info(NDI_UNIQUE, 0, op, "The gods won't let you throw that."); |
1483 | new_draw_info(NDI_UNIQUE, 0, op, "The gods won't let you throw that."); |
1484 | } |
1484 | } |
1485 | return 0; |
1485 | return 0; |
1486 | } |
1486 | } |
1487 | |
1487 | |
1488 | /* Because throwing effectiveness must be reduced by the |
1488 | /* Because throwing effectiveness must be reduced by the |
1489 | * encumbrance of the thrower and weight of the object. THus, |
1489 | * encumbrance of the thrower and weight of the object. THus, |
1490 | * we use the concept of 'effective strength' as defined below. |
1490 | * we use the concept of 'effective strength' as defined below. |
1491 | */ |
1491 | */ |
1492 | |
1492 | |
1493 | /* if str exceeds MAX_STAT (30, eg giants), lets assign a str_factor > 1 */ |
1493 | /* if str exceeds MAX_STAT (30, eg giants), lets assign a str_factor > 1 */ |
1494 | if(str>MAX_STAT) { |
1494 | if(str>MAX_STAT) { |
1495 | str_factor = (float) str /(float) MAX_STAT; str = MAX_STAT; |
1495 | str_factor = (float) str /(float) MAX_STAT; str = MAX_STAT; |
1496 | } |
1496 | } |
1497 | |
1497 | |
1498 | /* the more we carry, the less we can throw. Limit only on players */ |
1498 | /* the more we carry, the less we can throw. Limit only on players */ |
1499 | maxc=max_carry[str]*1000; |
1499 | maxc=max_carry[str]*1000; |
1500 | if(op->carrying>maxc&&op->type==PLAYER) |
1500 | if(op->carrying>maxc&&op->type==PLAYER) |
1501 | load_factor = (float)maxc/(float) op->carrying; |
1501 | load_factor = (float)maxc/(float) op->carrying; |
1502 | |
1502 | |
1503 | /* lighter items are thrown harder, farther, faster */ |
1503 | /* lighter items are thrown harder, farther, faster */ |
1504 | if(throw_ob->weight>0) |
1504 | if(throw_ob->weight>0) |
1505 | item_factor = (float) maxc/(float) (3.0 * throw_ob->weight); |
1505 | item_factor = (float) maxc/(float) (3.0 * throw_ob->weight); |
1506 | else { /* 0 or negative weight?!? Odd object, can't throw it */ |
1506 | else { /* 0 or negative weight?!? Odd object, can't throw it */ |
1507 | new_draw_info_format(NDI_UNIQUE, 0,op,"You can't throw %s.\n", |
1507 | new_draw_info_format(NDI_UNIQUE, 0,op,"You can't throw %s.\n", |
1508 | query_name(throw_ob)); |
1508 | query_name(throw_ob)); |
1509 | return 0; |
1509 | return 0; |
1510 | } |
1510 | } |
1511 | |
1511 | |
1512 | eff_str = (int) (str * (load_factor<1.0?load_factor:1.0)); |
1512 | eff_str = (int) (str * (load_factor<1.0?load_factor:1.0)); |
1513 | eff_str = (int) ((float) eff_str * item_factor * str_factor); |
1513 | eff_str = (int) ((float) eff_str * item_factor * str_factor); |
1514 | |
1514 | |
… | |
… | |
1531 | mflags = get_map_flags(part->map,&m, part->x+freearr_x[dir],part->y+freearr_y[dir],&sx,&sy); |
1531 | mflags = get_map_flags(part->map,&m, part->x+freearr_x[dir],part->y+freearr_y[dir],&sx,&sy); |
1532 | |
1532 | |
1533 | if(!dir || (eff_str <= 1) || (mflags & P_OUT_OF_MAP) || |
1533 | if(!dir || (eff_str <= 1) || (mflags & P_OUT_OF_MAP) || |
1534 | (GET_MAP_MOVE_BLOCK(m, sx, sy) & MOVE_FLY_LOW)) { |
1534 | (GET_MAP_MOVE_BLOCK(m, sx, sy) & MOVE_FLY_LOW)) { |
1535 | |
1535 | |
1536 | /* bounces off 'wall', and drops to feet */ |
1536 | /* bounces off 'wall', and drops to feet */ |
1537 | remove_ob(throw_ob); |
1537 | remove_ob(throw_ob); |
1538 | throw_ob->x = part->x; throw_ob->y = part->y; |
1538 | throw_ob->x = part->x; throw_ob->y = part->y; |
1539 | insert_ob_in_map(throw_ob,part->map,op,0); |
1539 | insert_ob_in_map(throw_ob,part->map,op,0); |
1540 | if(op->type==PLAYER) { |
1540 | if(op->type==PLAYER) { |
1541 | if(eff_str<=1) { |
1541 | if(eff_str<=1) { |
1542 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1542 | new_draw_info_format(NDI_UNIQUE, 0,op, |
1543 | "Your load is so heavy you drop %s to the ground.", |
1543 | "Your load is so heavy you drop %s to the ground.", |
1544 | query_name(throw_ob)); |
1544 | query_name(throw_ob)); |
1545 | } |
1545 | } |
1546 | else if(!dir) { |
1546 | else if(!dir) { |
1547 | new_draw_info_format(NDI_UNIQUE, 0,op,"You throw %s at the ground.", |
1547 | new_draw_info_format(NDI_UNIQUE, 0,op,"You throw %s at the ground.", |
1548 | query_name(throw_ob)); |
1548 | query_name(throw_ob)); |
1549 | } |
1549 | } |
1550 | else |
1550 | else |
1551 | new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); |
1551 | new_draw_info(NDI_UNIQUE, 0,op,"Something is in the way."); |
1552 | } |
1552 | } |
1553 | return 0; |
1553 | return 0; |
1554 | } /* if object can't be thrown */ |
1554 | } /* if object can't be thrown */ |
1555 | |
1555 | |
1556 | left = throw_ob; /* these are throwing objects left to the player */ |
1556 | left = throw_ob; /* these are throwing objects left to the player */ |
1557 | left_tag = left->count; |
1557 | left_tag = left->count; |
1558 | |
1558 | |
1559 | /* sometimes get_split_ob can't split an object (because op->nrof==0?) |
1559 | /* sometimes get_split_ob can't split an object (because op->nrof==0?) |
1560 | * and returns NULL. We must use 'left' then |
1560 | * and returns NULL. We must use 'left' then |
1561 | */ |
1561 | */ |
1562 | |
1562 | |
1563 | if((throw_ob = get_split_ob(throw_ob, 1))==NULL) { |
1563 | if((throw_ob = get_split_ob(throw_ob, 1))==NULL) { |
1564 | throw_ob = left; |
1564 | throw_ob = left; |
1565 | remove_ob(left); |
1565 | remove_ob(left); |
1566 | if (op->type==PLAYER) |
1566 | if (op->type==PLAYER) |
1567 | esrv_del_item(op->contr, left->count); |
1567 | esrv_del_item(op->contr, left->count); |
1568 | } |
1568 | } |
1569 | else if (op->type==PLAYER) { |
1569 | else if (op->type==PLAYER) { |
1570 | if (was_destroyed (left, left_tag)) |
1570 | if (was_destroyed (left, left_tag)) |
1571 | esrv_del_item(op->contr, left_tag); |
1571 | esrv_del_item(op->contr, left_tag); |
1572 | else |
1572 | else |
1573 | esrv_update_item(UPD_NROF, op, left); |
1573 | esrv_update_item(UPD_NROF, op, left); |
1574 | } |
1574 | } |
1575 | |
1575 | |
1576 | /* special case: throwing powdery substances like dust, dirt */ |
1576 | /* special case: throwing powdery substances like dust, dirt */ |
1577 | if(throw_ob->type == POTION && throw_ob->subtype == POT_DUST) { |
1577 | if(throw_ob->type == POTION && throw_ob->subtype == POT_DUST) { |
1578 | cast_dust(op,throw_ob,dir); |
1578 | cast_dust(op,throw_ob,dir); |
1579 | return 1; |
1579 | return 1; |
1580 | } |
1580 | } |
1581 | |
1581 | |
1582 | /* Make a thrown object -- insert real object in a 'carrier' object. |
1582 | /* Make a thrown object -- insert real object in a 'carrier' object. |
1583 | * If unsuccessfull at making the "thrown_obj", we just reinsert |
1583 | * If unsuccessfull at making the "thrown_obj", we just reinsert |
1584 | * the original object back into inventory and exit |
1584 | * the original object back into inventory and exit |
1585 | */ |
1585 | */ |
1586 | if((toss_item = make_throw_ob(throw_ob))) { |
1586 | if((toss_item = make_throw_ob(throw_ob))) { |
1587 | throw_ob = toss_item; |
1587 | throw_ob = toss_item; |
1588 | if (throw_ob->skill) free_string(throw_ob->skill); |
1588 | if (throw_ob->skill) free_string(throw_ob->skill); |
1589 | throw_ob->skill = add_string(skill->skill); |
1589 | throw_ob->skill = add_string(skill->skill); |
1590 | } |
1590 | } |
1591 | else { |
1591 | else { |
1592 | insert_ob_in_ob(throw_ob,op); |
1592 | insert_ob_in_ob(throw_ob,op); |
1593 | return 0; |
1593 | return 0; |
1594 | } |
1594 | } |
1595 | |
1595 | |
1596 | set_owner(throw_ob,op); |
1596 | set_owner(throw_ob,op); |
1597 | /* At some point in the attack code, the actual real object (op->inv) |
1597 | /* At some point in the attack code, the actual real object (op->inv) |
1598 | * becomes the hitter. As such, we need to make sure that has a proper |
1598 | * becomes the hitter. As such, we need to make sure that has a proper |
… | |
… | |
1623 | /* chance of breaking. Proportional to force used and weight of item */ |
1623 | /* chance of breaking. Proportional to force used and weight of item */ |
1624 | throw_ob->stats.food = (dam/2) + (throw_ob->weight/60000); |
1624 | throw_ob->stats.food = (dam/2) + (throw_ob->weight/60000); |
1625 | |
1625 | |
1626 | /* replace 25 with a call to clone.arch wc? messes up w/ NPC */ |
1626 | /* replace 25 with a call to clone.arch wc? messes up w/ NPC */ |
1627 | throw_ob->stats.wc = 25 - dex_bonus[op->stats.Dex] |
1627 | throw_ob->stats.wc = 25 - dex_bonus[op->stats.Dex] |
1628 | - thaco_bonus[eff_str] - skill->level; |
1628 | - thaco_bonus[eff_str] - skill->level; |
1629 | |
1629 | |
1630 | |
1630 | |
1631 | /* the properties of objects which are meant to be thrown (ie dart, |
1631 | /* the properties of objects which are meant to be thrown (ie dart, |
1632 | * throwing knife, etc) will differ from ordinary items. Lets tailor |
1632 | * throwing knife, etc) will differ from ordinary items. Lets tailor |
1633 | * this stuff in here. |
1633 | * this stuff in here. |
1634 | */ |
1634 | */ |
1635 | |
1635 | |
1636 | if(QUERY_FLAG(throw_ob->inv,FLAG_IS_THROWN)) { |
1636 | if(QUERY_FLAG(throw_ob->inv,FLAG_IS_THROWN)) { |
1637 | throw_ob->last_sp += eff_str/3; /* fly a little further */ |
1637 | throw_ob->last_sp += eff_str/3; /* fly a little further */ |
1638 | throw_ob->stats.dam += throw_ob->inv->stats.dam + throw_ob->magic + 2; |
1638 | throw_ob->stats.dam += throw_ob->inv->stats.dam + throw_ob->magic + 2; |
1639 | throw_ob->stats.wc -= throw_ob->magic + throw_ob->inv->stats.wc; |
1639 | throw_ob->stats.wc -= throw_ob->magic + throw_ob->inv->stats.wc; |
1640 | /* only throw objects get directional faces */ |
1640 | /* only throw objects get directional faces */ |
1641 | if(GET_ANIM_ID(throw_ob) && NUM_ANIMATIONS(throw_ob)) |
1641 | if(GET_ANIM_ID(throw_ob) && NUM_ANIMATIONS(throw_ob)) |
1642 | SET_ANIMATION(throw_ob, dir); |
1642 | SET_ANIMATION(throw_ob, dir); |
1643 | } else { |
1643 | } else { |
1644 | /* some materials will adjust properties.. */ |
1644 | /* some materials will adjust properties.. */ |
1645 | if(throw_ob->material&M_LEATHER) { |
1645 | if(throw_ob->material&M_LEATHER) { |
1646 | throw_ob->stats.dam -= 1; |
1646 | throw_ob->stats.dam -= 1; |
1647 | throw_ob->stats.food -= 10; |
1647 | throw_ob->stats.food -= 10; |
1648 | } |
1648 | } |
1649 | if(throw_ob->material&M_GLASS) throw_ob->stats.food += 60; |
1649 | if(throw_ob->material&M_GLASS) throw_ob->stats.food += 60; |
1650 | |
1650 | |
1651 | if(throw_ob->material&M_ORGANIC) { |
1651 | if(throw_ob->material&M_ORGANIC) { |
1652 | throw_ob->stats.dam -= 3; |
1652 | throw_ob->stats.dam -= 3; |
1653 | throw_ob->stats.food += 55; |
1653 | throw_ob->stats.food += 55; |
1654 | } |
1654 | } |
1655 | if(throw_ob->material&M_PAPER||throw_ob->material&M_CLOTH) { |
1655 | if(throw_ob->material&M_PAPER||throw_ob->material&M_CLOTH) { |
1656 | throw_ob->stats.dam -= 5; throw_ob->speed *= 0.8; |
1656 | throw_ob->stats.dam -= 5; throw_ob->speed *= 0.8; |
1657 | throw_ob->stats.wc += 3; throw_ob->stats.food -= 30; |
1657 | throw_ob->stats.wc += 3; throw_ob->stats.food -= 30; |
1658 | } |
1658 | } |
1659 | /* light obj have more wind resistance, fly slower*/ |
1659 | /* light obj have more wind resistance, fly slower*/ |
1660 | if(throw_ob->weight>500) throw_ob->speed *= 0.8; |
1660 | if(throw_ob->weight>500) throw_ob->speed *= 0.8; |
1661 | if(throw_ob->weight>50) throw_ob->speed *= 0.5; |
1661 | if(throw_ob->weight>50) throw_ob->speed *= 0.5; |
1662 | |
1662 | |
1663 | } /* else tailor thrown object */ |
1663 | } /* else tailor thrown object */ |
1664 | |
1664 | |
1665 | /* some limits, and safeties (needed?) */ |
1665 | /* some limits, and safeties (needed?) */ |
1666 | if(throw_ob->stats.dam<0) throw_ob->stats.dam=0; |
1666 | if(throw_ob->stats.dam<0) throw_ob->stats.dam=0; |
… | |
… | |
1711 | |
1711 | |
1712 | int skill_throw (object *op, object *part, int dir, const char *params, object *skill) { |
1712 | int skill_throw (object *op, object *part, int dir, const char *params, object *skill) { |
1713 | object *throw_ob; |
1713 | object *throw_ob; |
1714 | |
1714 | |
1715 | if(op->type==PLAYER) |
1715 | if(op->type==PLAYER) |
1716 | throw_ob = find_throw_ob(op,params); |
1716 | throw_ob = find_throw_ob(op,params); |
1717 | else |
1717 | else |
1718 | throw_ob = find_mon_throw_ob(op); |
1718 | throw_ob = find_mon_throw_ob(op); |
1719 | |
1719 | |
1720 | return do_throw(op,part, throw_ob,dir, skill); |
1720 | return do_throw(op,part, throw_ob,dir, skill); |
1721 | } |
1721 | } |