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

Comparing deliantra/server/server/skills.C (file contents):
Revision 1.97 by elmex, Thu Apr 28 15:09:25 2011 UTC vs.
Revision 1.108 by root, Wed Dec 12 02:13:05 2012 UTC

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 (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2003 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2003 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 8 * 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 9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the Affero GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>. 20 * <http://www.gnu.org/licenses/>.
21 * 21 *
22 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
23 */ 23 */
24 24
25#include <global.h> 25#include <global.h>
26#include <object.h> 26#include <object.h>
281 281
282 /* For all the stacked objects at this point, attempt a steal */ 282 /* For all the stacked objects at this point, attempt a steal */
283 for (; tmp; tmp = next) 283 for (; tmp; tmp = next)
284 { 284 {
285 next = tmp->below; 285 next = tmp->below;
286 /* Minor hack--for multi square beings - make sure we get 286 /* Minor hack--for multi square beings - make sure we get
287 * the 'head' coz 'tail' objects have no inventory! - b.t. 287 * the 'head' coz 'tail' objects have no inventory! - b.t.
288 */ 288 */
289 if (tmp->head) 289 if (tmp->head)
290 tmp = tmp->head; 290 tmp = tmp->head;
291 291
292 if (tmp->type != PLAYER && !tmp->flag [FLAG_MONSTER]) 292 if (tmp->type != PLAYER && !tmp->flag [FLAG_MONSTER])
293 continue;
294
295 /* do not reveal hidden DMs */
296 if (tmp->type == PLAYER && tmp->flag [FLAG_WIZ] && tmp->contr->hidden)
297 continue; 293 continue;
298 294
299 if (attempt_steal (tmp, op, skill)) 295 if (attempt_steal (tmp, op, skill))
300 { 296 {
301 if (tmp->type == PLAYER) /* no xp for stealing from another player */ 297 if (tmp->type == PLAYER) /* no xp for stealing from another player */
355 351
356int 352int
357pick_lock (object *pl, int dir, object *skill) 353pick_lock (object *pl, int dir, object *skill)
358{ 354{
359 object *tmp; 355 object *tmp;
360 int x = pl->x + freearr_x[dir];
361 int y = pl->y + freearr_y[dir];
362 356
363 if (!dir) 357 if (!dir)
364 dir = pl->facing; 358 dir = pl->facing;
365 359
360 mapxy pos (pl); pos.move (dir);
361
366 /* For all the stacked objects at this point find a door */ 362 /* For all the stacked objects at this point find a door */
367 if (out_of_map (pl->map, x, y)) 363 if (!pos.normalise ())
368 { 364 {
369 pl->failmsg ("There is no lock there."); 365 pl->failmsg ("There is no lock there.");
370 return 0; 366 return 0;
371 } 367 }
372 368
373 for (tmp = GET_MAP_OB (pl->map, x, y); tmp; tmp = tmp->above) 369 for (tmp = pos->bot; tmp; tmp = tmp->above)
374 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) 370 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR)
375 break; 371 break;
376 372
377 if (!tmp) 373 if (!tmp)
378 { 374 {
519 } 515 }
520 516
521 for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above) 517 for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above)
522 { 518 {
523 /* Jump into creature */ 519 /* Jump into creature */
524 if (tmp->flag [FLAG_MONSTER] 520 if (tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER)
525 || (tmp->type == PLAYER && (!tmp->flag [FLAG_WIZ] || !tmp->contr->hidden)))
526 { 521 {
527 new_draw_info_format (NDI_UNIQUE, 0, pl, "You jump into %s%s.", tmp->type == PLAYER ? "" : "the ", &tmp->name); 522 new_draw_info_format (NDI_UNIQUE, 0, pl, "You jump into %s%s.", tmp->type == PLAYER ? "" : "the ", &tmp->name);
528 523
529 stop_jump (pl, i, spaces); 524 stop_jump (pl, i, spaces);
530 525
587 } 582 }
588 583
589 return attempt_jump (pl, dir, spaces, skill); 584 return attempt_jump (pl, dir, spaces, skill);
590} 585}
591 586
592/* skill_ident() - this code is supposed to allow players to identify 587/* skill_ident() - this code is supposed to allow players to identify
593 * classes of objects with the various "auto-ident" skills. Player must 588 * classes of objects with the various "auto-ident" skills. Player must
594 * have unidentified objects of the right type in order for the skill 589 * have unidentified objects of the right type in order for the skill
595 * to work. While multiple classes of objects may be identified, 590 * to work. While multiple classes of objects may be identified,
596 * this code is kind of yucky -- it would be nice to make it a bit 591 * this code is kind of yucky -- it would be nice to make it a bit
597 * more generalized. Right now, skill indices are embedded in this routine. 592 * more generalized. Right now, skill indices are embedded in this routine.
598 * Returns amount of experience gained (on successful ident). 593 * Returns amount of experience gained (on successful ident).
599 * - b.t. (thomas@astro.psu.edu) 594 * - b.t. (thomas@astro.psu.edu)
600 */ 595 */
601static int 596static int
602do_skill_detect_curse (object *pl, object *skill) 597do_skill_detect_curse (object *pl, object *skill)
603{ 598{
604 int success = 0; 599 int success = 0;
930 * of anything better! -b.t. 925 * of anything better! -b.t.
931 */ 926 */
932int 927int
933singing (object *pl, int dir, object *skill) 928singing (object *pl, int dir, object *skill)
934{ 929{
935 int i, exp = 0; 930 int exp = 0;
936 object *tmp; 931 object *tmp;
937 maptile *m; 932 maptile *m;
938 sint16 x, y; 933 sint16 x, y;
939 934
940 if (pl->type != PLAYER) 935 if (pl->type != PLAYER)
1213 1208
1214 /* ok let's meditate! Spell points are regained first, then once 1209 /* ok let's meditate! Spell points are regained first, then once
1215 * they are maxed we get back hp. Actual incrementing of values 1210 * they are maxed we get back hp. Actual incrementing of values
1216 * is handled by the do_some_living() (in player.c). This way magical 1211 * is handled by the do_some_living() (in player.c). This way magical
1217 * bonuses for healing/sp regeneration are included properly 1212 * bonuses for healing/sp regeneration are included properly
1218 * No matter what, we will eat up some playing time trying to 1213 * No matter what, we will eat up some playing time trying to
1219 * meditate. (see 'factor' variable for what sets the amount of time) 1214 * meditate. (see 'factor' variable for what sets the amount of time)
1220 */ 1215 */
1221 1216
1222 new_draw_info (NDI_BLACK, 0, pl, "You meditate."); 1217 new_draw_info (NDI_BLACK, 0, pl, "You meditate.");
1223 1218
1224 if (pl->stats.sp < pl->stats.maxsp) 1219 if (pl->stats.sp < pl->stats.maxsp)
1231 pl->stats.hp++; 1226 pl->stats.hp++;
1232 pl->last_heal = -1; 1227 pl->last_heal = -1;
1233 } 1228 }
1234} 1229}
1235 1230
1236/* write_note() - this routine allows players to inscribe messages in 1231/* write_note() - this routine allows players to inscribe messages in
1237 * ordinary inscribable 'books' (anything that is not a SPELL). b.t. 1232 * ordinary inscribable 'books' (anything that is not a SPELL). b.t.
1238 */ 1233 */
1239static int 1234static int
1240write_note (object *pl, object *item, const char *msg, object *skill) 1235write_note (object *pl, object *item, const char *msg, object *skill)
1241{ 1236{
1286 return 0; 1281 return 0;
1287} 1282}
1288 1283
1289/* write_scroll() - this routine allows players to inscribe spell scrolls 1284/* write_scroll() - this routine allows players to inscribe spell scrolls
1290 * of spells which they know. Backfire effects are possible with the 1285 * of spells which they know. Backfire effects are possible with the
1291 * severity of the backlash correlated with the difficulty of the scroll 1286 * severity of the backlash correlated with the difficulty of the scroll
1292 * that is attempted. -b.t. thomas@astro.psu.edu 1287 * that is attempted. -b.t. thomas@astro.psu.edu
1293 */ 1288 */
1294static int 1289static int
1295write_scroll (object *pl, object *scroll, object *skill) 1290write_scroll (object *pl, object *scroll, object *skill)
1296{ 1291{
1328 if (random_roll (0, chosen_spell->level * 4 - 1, pl, PREFER_LOW) < skill->level) 1323 if (random_roll (0, chosen_spell->level * 4 - 1, pl, PREFER_LOW) < skill->level)
1329 { 1324 {
1330 object *newscroll = scroll->other_arch->instance (); 1325 object *newscroll = scroll->other_arch->instance ();
1331 scroll->decrease (); 1326 scroll->decrease ();
1332 newscroll->nrof = 1; 1327 newscroll->nrof = 1;
1328 newscroll->randomitems = 0; // make sure randomitems doesn't destroy the scroll
1333 1329
1334 pl->contr->play_sound (sound_find ("inscribe_success")); 1330 pl->contr->play_sound (sound_find ("inscribe_success"));
1335 1331
1336 if (!confused) 1332 if (!confused)
1337 { 1333 {
1348 newscroll->level = max (skill->level, chosen_spell->level); 1344 newscroll->level = max (skill->level, chosen_spell->level);
1349 new_draw_info (NDI_UNIQUE, 0, pl, "In your confused state, you write down some odd spell."); 1345 new_draw_info (NDI_UNIQUE, 0, pl, "In your confused state, you write down some odd spell.");
1350 } 1346 }
1351 1347
1352 object *tmp = chosen_spell->clone (); 1348 object *tmp = chosen_spell->clone ();
1349 tmp->flag [FLAG_APPLIED] = false;
1353 insert_ob_in_ob (tmp, newscroll); 1350 insert_ob_in_ob (tmp, newscroll);
1354 1351
1355 /* Same code as from treasure.C - so they can better merge. 1352 /* Same code as from treasure.C - so they can better merge.
1356 * if players want to sell them, so be it. 1353 * if players want to sell them, so be it.
1357 */ 1354 */
1827 throw_ob = find_throw_ob (op, params); 1824 throw_ob = find_throw_ob (op, params);
1828 else 1825 else
1829 throw_ob = find_mon_throw_ob (op); 1826 throw_ob = find_mon_throw_ob (op);
1830 1827
1831 return do_throw (op, part, throw_ob, dir, skill); 1828 return do_throw (op, part, throw_ob, dir, skill);
1829}
1830
1831static void
1832give_player_quad_material_for (object *pl, object *ob)
1833{
1834 if (!ob->flag [FLAG_IS_QUAD] || !ob->other_arch)
1835 return;
1836
1837 object *t = ob->other_arch->instance ();
1838 pl->insert (t);
1832} 1839}
1833 1840
1834bool 1841bool
1835skill_mining (object *who, object *tool, object *skill, int dir, const char *string) 1842skill_mining (object *who, object *tool, object *skill, int dir, const char *string)
1836{ 1843{
1901 else if (mine_obj->flag [FLAG_IS_QUAD]) 1908 else if (mine_obj->flag [FLAG_IS_QUAD])
1902 { 1909 {
1903 if (mine_obj->flag [FLAG_IS_FLOOR]) 1910 if (mine_obj->flag [FLAG_IS_FLOOR])
1904 { 1911 {
1905 maptile *lower_floor = pos.m->tile_available (TILE_DOWN); 1912 maptile *lower_floor = pos.m->tile_available (TILE_DOWN);
1913
1906 if (!lower_floor) 1914 if (!lower_floor)
1907 { 1915 {
1908 who->failmsgf ( 1916 who->failmsgf (
1909 "Whoops, your attempt to remove the floor failed. " 1917 "Whoops, you failed to remove the %s. H<You may try again.>",
1910 "H<Try it again until it works.>" 1918 &mine_obj->name
1911 ); 1919 );
1912 return false; 1920 return false;
1913 } 1921 }
1914 1922
1915 mapxy below_pos (lower_floor, pos.x, pos.y); 1923 mapxy below_pos (lower_floor, pos.x, pos.y);
1924
1916 if (!below_pos.normalise ()) 1925 if (!below_pos.normalise ())
1917 { 1926 {
1918 who->failmsgf ( 1927 who->failmsgf (
1919 "Whoops, your attempt to remove the floor failed. " 1928 "Whoops, you failed to remove the %s. H<You may try again.>",
1920 "H<Try it again until it works.>" 1929 &mine_obj->name
1921 ); 1930 );
1922 return false; 1931 return false;
1923 } 1932 }
1924 1933
1925 // first insert open space here: 1934 // first insert open space here:
1926 struct archetype *open_space_arch = archetype::find (shstr_quad_open_space); 1935 object *open_space_floor = archetype::get (shstr_quad_open_space);
1927 if (!open_space_arch)
1928 {
1929 who->failmsgf (
1930 "Ouch, the quad building system is broken. Contact a dungeon master!"
1931 );
1932 return false;
1933 }
1934
1935 object *open_space_floor = open_space_arch->instance ();
1936 open_space_floor->stats.hp = pos.x; 1936 open_space_floor->stats.hp = pos.x;
1937 open_space_floor->stats.sp = pos.y; 1937 open_space_floor->stats.sp = pos.y;
1938 insert_ob_in_map_at ( 1938 insert_ob_in_map_at (open_space_floor, pos.m, mine_obj,
1939 open_space_floor, pos.m, mine_obj, INS_BELOW_ORIGINATOR, pos.x, pos.y); 1939 INS_BELOW_ORIGINATOR, pos.x, pos.y);
1940 1940
1941 // next we will remove the wall in the lower layer: 1941 // next we will remove the wall in the lower layer:
1942 mapspace &below_ms = below_pos.ms (); 1942 mapspace &below_ms = below_pos.ms ();
1943 for (object *quad_obj = below_ms.top; quad_obj; quad_obj = quad_obj->below) 1943 for (object *quad_obj = below_ms.top; quad_obj; quad_obj = quad_obj->below)
1944 { 1944 {
1945 if (quad_obj->flag [FLAG_IS_FLOOR]) 1945 if (quad_obj->flag [FLAG_IS_FLOOR])
1946 break; 1946 break;
1947 1947
1948 if (quad_obj->flag [FLAG_IS_QUAD]) 1948 if (quad_obj->flag [FLAG_IS_QUAD])
1949 { 1949 {
1950 quad_obj->map->queue_physics_at (quad_obj->x, quad_obj->y);
1951 give_player_quad_material_for (who, quad_obj);
1950 quad_obj->remove (); 1952 quad_obj->destroy ();
1951 who->insert (quad_obj);
1952 break; 1953 break;
1953 } 1954 }
1954 } 1955 }
1955 } 1956 }
1956 1957
1958 mine_obj->map->queue_physics_at (mine_obj->x, mine_obj->y);
1959
1957 // FIXME: there should be chance assigned, like above with veins! 1960 // FIXME: there should be chance assigned, like above with veins!
1958 who->play_sound (tool->sound); 1961 who->play_sound (tool->sound);
1959 who->insert (mine_obj); 1962 give_player_quad_material_for (who, mine_obj);
1963 mine_obj->destroy ();
1964 who->contr->fire_on = 0; // TODO: stopgap, do not remove more than one per keypress
1960 return true; 1965 return true;
1961 } 1966 }
1962 1967
1963 return false; 1968 return false;
1964} 1969}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines