1 | /* |
1 | /* |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
2 | * This file is part of Deliantra, the Roguelike Realtime MMORPG. |
3 | * |
3 | * |
|
|
4 | * Copyright (©) 2018 Marc Alexander Lehmann / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2003 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 2003 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
8 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * the terms of the Affero GNU General Public License as published by the |
10 | * the terms of the Affero GNU General Public License as published by the |
… | |
… | |
28 | |
29 | |
29 | #ifndef sqr |
30 | #ifndef sqr |
30 | # define sqr(x) ((x)*(x)) |
31 | # define sqr(x) ((x)*(x)) |
31 | #endif |
32 | #endif |
32 | |
33 | |
33 | /* peterm: |
34 | /* peterm: |
34 | * write_rune: |
35 | * write_rune: |
35 | * op: rune writer |
36 | * op: rune writer |
36 | * skop: skill object used for casting this rune |
37 | * skop: skill object used for casting this rune |
37 | * dir: orientation of rune, direction rune's contained spell will |
38 | * dir: orientation of rune, direction rune's contained spell will |
38 | * be cast in, if applicable |
39 | * be cast in, if applicable |
39 | * spell: spell object to put into the rune |
40 | * spell: spell object to put into the rune |
40 | * level: level of casting of the rune |
41 | * level: level of casting of the rune |
41 | * runename: name of the rune or message displayed by the rune for |
42 | * runename: name of the rune or message displayed by the rune for |
42 | * a rune of marking |
43 | * a rune of marking |
43 | */ |
44 | */ |
44 | int |
45 | int |
45 | write_rune (object *op, object *caster, object *spell, int dir, const char *runename) |
46 | write_rune (object *op, object *caster, object *spell, int dir, const char *runename) |
46 | { |
47 | { |
47 | object *tmp, *rune_spell, *rune; |
48 | object *tmp, *rune_spell, *rune; |
48 | maptile *m; |
|
|
49 | sint16 nx, ny; |
|
|
50 | |
49 | |
51 | if (!dir) |
50 | if (!dir) |
52 | dir = 1; |
51 | dir = 1; |
53 | |
52 | |
54 | nx = op->x + freearr_x[dir]; |
53 | mapxy pos (op); |
55 | ny = op->y + freearr_y[dir]; |
54 | pos.move (dir); |
56 | m = op->map; |
|
|
57 | |
55 | |
58 | if (get_map_flags (m, &m, nx, ny, &nx, &ny) & (P_OUT_OF_MAP | P_SAFE | P_NO_MAGIC | P_NO_CLERIC)) |
56 | if (!pos.normalise () || pos.ms ().flags () & (P_SAFE | P_NO_MAGIC | P_NO_CLERIC)) |
59 | { |
57 | { |
60 | new_draw_info (NDI_UNIQUE, 0, op, "Can't make a rune there!"); |
58 | new_draw_info (NDI_UNIQUE, 0, op, "Your rune doesn't stick! H<You cannot place a rune on safe ground or outside the map.>"); |
61 | return 0; |
59 | return 0; |
62 | } |
60 | } |
63 | |
61 | |
|
|
62 | if (pos->blocks (op)) |
|
|
63 | { |
|
|
64 | new_draw_info (NDI_UNIQUE, 0, op, "You cannot reach there! H<You cannot place a rune where you can't go.>"); |
|
|
65 | return 0; |
|
|
66 | } |
|
|
67 | |
64 | for (tmp = m->at (nx, ny).bot; tmp; tmp = tmp->above) |
68 | for (tmp = pos->bot; tmp; tmp = tmp->above) |
65 | if (tmp->type == RUNE) |
69 | if (tmp->type == RUNE) |
66 | break; |
70 | break; |
67 | |
71 | |
68 | if (tmp) |
72 | if (tmp) |
69 | { |
73 | { |
… | |
… | |
156 | rune->stats.Cha = rune->level / 2; /* the invisibility parameter */ |
160 | rune->stats.Cha = rune->level / 2; /* the invisibility parameter */ |
157 | rune->direction = dir; /* where any spell will go upon detonation */ |
161 | rune->direction = dir; /* where any spell will go upon detonation */ |
158 | rune->set_owner (op); /* runes without need no owner */ |
162 | rune->set_owner (op); /* runes without need no owner */ |
159 | set_spell_skill (op, caster, spell, rune); |
163 | set_spell_skill (op, caster, spell, rune); |
160 | |
164 | |
161 | m->insert (rune, nx, ny, op); |
165 | pos.insert (rune, op); |
162 | return 1; |
166 | return 1; |
163 | } |
167 | } |
164 | |
168 | |
165 | /* move_rune: peterm |
169 | /* move_rune: peterm |
166 | comments on runes: |
170 | comments on runes: |
… | |
… | |
194 | if (op->invisible != det) |
198 | if (op->invisible != det) |
195 | update_object (op, UP_OBJ_CHANGE); |
199 | update_object (op, UP_OBJ_CHANGE); |
196 | } |
200 | } |
197 | |
201 | |
198 | /* peterm: rune_attack |
202 | /* peterm: rune_attack |
199 | * function handles those runes which detonate but do not cast spells. |
203 | * function handles those runes which detonate but do not cast spells. |
200 | */ |
204 | */ |
201 | static void |
205 | static void |
202 | rune_attack (object *op, object *victim) |
206 | rune_attack (object *op, object *victim) |
203 | { |
207 | { |
204 | if (victim) |
208 | if (victim) |
… | |
… | |
223 | else |
227 | else |
224 | hit_map (op, 0, op->attacktype, 1); |
228 | hit_map (op, 0, op->attacktype, 1); |
225 | } |
229 | } |
226 | |
230 | |
227 | /* This function generalizes attacks by runes/traps. This ought to make |
231 | /* This function generalizes attacks by runes/traps. This ought to make |
228 | * it possible for runes to attack from the inventory, |
232 | * it possible for runes to attack from the inventory, |
229 | * it'll spring the trap on the victim. |
233 | * it'll spring the trap on the victim. |
230 | */ |
234 | */ |
231 | void |
235 | void |
232 | spring_trap (object *trap, object *victim) |
236 | spring_trap (object *trap, object *victim) |
233 | { |
237 | { |
… | |
… | |
253 | |
257 | |
254 | if (victim && victim->type == PLAYER) |
258 | if (victim && victim->type == PLAYER) |
255 | new_draw_info (NDI_UNIQUE, 0, victim, trap->msg); |
259 | new_draw_info (NDI_UNIQUE, 0, victim, trap->msg); |
256 | |
260 | |
257 | /* Flash an image of the trap on the map so the poor sod |
261 | /* Flash an image of the trap on the map so the poor sod |
258 | * knows what hit him. |
262 | * knows what hit him. |
259 | */ |
263 | */ |
260 | env = trap->outer_env_or_self (); |
264 | env = trap->outer_env_or_self (); |
261 | |
265 | |
262 | /* If the victim is not next to this trap, don't set it off. |
266 | /* If the victim is not next to this trap, don't set it off. |
263 | * players shouldn't get hit by firing arrows at a door for example. |
267 | * players shouldn't get hit by firing arrows at a door for example. |
… | |
… | |
313 | trap->stats.food = 20; /* make it stick around until its spells are gone */ |
317 | trap->stats.food = 20; /* make it stick around until its spells are gone */ |
314 | trap->set_flag (FLAG_IS_USED_UP); |
318 | trap->set_flag (FLAG_IS_USED_UP); |
315 | } |
319 | } |
316 | } |
320 | } |
317 | |
321 | |
318 | /* dispel_rune: by peterm |
322 | /* dispel_rune: by peterm |
319 | * dispels the target rune, depending on the level of the actor |
323 | * dispels the target rune, depending on the level of the actor |
320 | * and the level of the rune risk flag, if true, means that there is |
324 | * and the level of the rune risk flag, if true, means that there is |
321 | * a chance that the trap/rune will detonate |
325 | * a chance that the trap/rune will detonate |
322 | */ |
326 | */ |
323 | int |
327 | int |
324 | dispel_rune (object *op, object *caster, object *spell, object *skill, int dir) |
328 | dispel_rune (object *op, object *caster, object *spell, object *skill, int dir) |
325 | { |
329 | { |
326 | object *tmp, *tmp2; |
330 | object *tmp, *tmp2; |
327 | int searchflag = 1, mflags; |
331 | int searchflag = 1, mflags; |
328 | sint16 x, y; |
332 | sint16 x, y; |
329 | maptile *m; |
333 | maptile *m; |
330 | |
334 | |
331 | x = op->x + freearr_x[dir]; |
335 | x = op->x + DIRX (dir); |
332 | y = op->y + freearr_y[dir]; |
336 | y = op->y + DIRY (dir); |
333 | m = op->map; |
337 | m = op->map; |
334 | |
338 | |
335 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
339 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
336 | |
340 | |
337 | /* Should we perhaps not allow player to disable traps if a monster/ |
341 | /* Should we perhaps not allow player to disable traps if a monster/ |
338 | * player is standing on top? |
342 | * player is standing on top? |
339 | */ |
343 | */ |
340 | if (mflags & P_OUT_OF_MAP) |
344 | if (mflags & P_OUT_OF_MAP) |
341 | { |
345 | { |
342 | new_draw_info (NDI_UNIQUE, 0, op, "There's nothing there!"); |
346 | new_draw_info (NDI_UNIQUE, 0, op, "There's nothing there!"); |
343 | return 0; |
347 | return 0; |
… | |
… | |
451 | return 0; |
455 | return 0; |
452 | } |
456 | } |
453 | } |
457 | } |
454 | |
458 | |
455 | /* traps need to be adjusted for the difficulty of the map. The |
459 | /* traps need to be adjusted for the difficulty of the map. The |
456 | * default traps are too strong for wimpy level 1 players, and |
460 | * default traps are too strong for wimpy level 1 players, and |
457 | * unthreatening to anyone of high level |
461 | * unthreatening to anyone of high level |
458 | */ |
462 | */ |
459 | void |
463 | void |
460 | trap_adjust (object *trap, int difficulty) |
464 | trap_adjust (object *trap, int difficulty) |
461 | { |
465 | { |
462 | int i; |
466 | int i; |
463 | |
467 | |
464 | /* now we set the trap level to match the difficulty of the level |
468 | /* now we set the trap level to match the difficulty of the level |
465 | * the formula below will give a level from 1 to (2*difficulty) with |
469 | * the formula below will give a level from 1 to (2*difficulty) with |
466 | * a peak probability at difficulty |
470 | * a peak probability at difficulty |
467 | */ |
471 | */ |
468 | |
472 | |
469 | trap->level = rndm (0, difficulty - 1) + rndm (0, difficulty - 1); |
473 | trap->level = rndm (0, difficulty - 1) + rndm (0, difficulty - 1); |
470 | if (trap->level < 1) |
474 | if (trap->level < 1) |
471 | trap->level = 1; |
475 | trap->level = 1; |