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.22 by root, Mon Jan 8 01:19:04 2007 UTC vs.
Revision 1.32 by root, Thu May 17 14:14:55 2007 UTC

1/* 1/*
2 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game
3 3 *
4 Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team 4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5 Copyright (C) 2003 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2003 Mark Wedel & Crossfire Development Team
6 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
7 7 *
8 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version. 11 * (at your 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 GNU General Public License 18 * You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 21 *
22 The authors can be reached via e-mail to <crossfire@schmorp.de> 22 * The authors can be reached via e-mail to <crossfire@schmorp.de>
23*/ 23 */
24 24
25#include <global.h> 25#include <global.h>
26#include <object.h> 26#include <object.h>
27#ifndef __CEXTRACT__
28# include <sproto.h> 27#include <sproto.h>
29#endif
30#include <living.h> 28#include <living.h>
31#include <skills.h> 29#include <skills.h>
32#include <spells.h> 30#include <spells.h>
33#include <book.h> 31#include <book.h>
34 32
42 return -1; 40 return -1;
43 41
44 /* Only prohibit stealing if the player does not have a free 42 /* Only prohibit stealing if the player does not have a free
45 * hand available and in fact does have hands. 43 * hand available and in fact does have hands.
46 */ 44 */
47 if (op->type == PLAYER && op->body_used[BODY_ARMS] <= 0 && op->body_info[BODY_ARMS]) 45 if (op->type == PLAYER && op->slot[body_arm].used <= 0 && op->slot[body_arm].info)
48 { 46 {
49 new_draw_info (NDI_UNIQUE, 0, op, "But you have no free hands to steal with!"); 47 new_draw_info (NDI_UNIQUE, 0, op, "But you have no free hands to steal with!");
50 return -1; 48 return -1;
51 } 49 }
52 50
95 * or not. 93 * or not.
96 * op is the target (person being pilfered) 94 * op is the target (person being pilfered)
97 * who is the person doing the stealing. 95 * who is the person doing the stealing.
98 * skill is the skill object (stealing). 96 * skill is the skill object (stealing).
99 */ 97 */
100
101static int 98static int
102attempt_steal (object *op, object *who, object *skill) 99attempt_steal (object *op, object *who, object *skill)
103{ 100{
104 object *success = NULL, *tmp = NULL, *next; 101 object *success = NULL, *tmp = NULL, *next;
105 int roll = 0, chance = 0, stats_value; 102 int roll = 0, chance = 0, stats_value;
123 else /* help npc to detect thief next time by raising its wisdom */ 120 else /* help npc to detect thief next time by raising its wisdom */
124 op->stats.Wis += (op->stats.Int / 5) + 1; 121 op->stats.Wis += (op->stats.Int / 5) + 1;
125 if (op->stats.Wis > MAX_STAT) 122 if (op->stats.Wis > MAX_STAT)
126 op->stats.Wis = MAX_STAT; 123 op->stats.Wis = MAX_STAT;
127 } 124 }
125
128 if (op->type == PLAYER && QUERY_FLAG (op, FLAG_WIZ)) 126 if (op->type == PLAYER && QUERY_FLAG (op, FLAG_WIZ))
129 { 127 {
130 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n"); 128 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n");
131 return 0; 129 return 0;
132 } 130 }
133#ifdef PROHIBIT_PLAYERKILL 131
132 // only allow stealing between hostile players (TODO: probably should change)
134 if (op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful)) 133 if (op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful))
135 { 134 {
136 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n"); 135 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
137 return 0; 136 return 0;
138 } 137 }
139#else
140 if (op->type == PLAYER && who->type == PLAYER && settings.no_player_stealing)
141 {
142 new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n");
143 return 0;
144 }
145#endif
146
147 138
148 /* Ok then, go thru their inventory, stealing */ 139 /* Ok then, go thru their inventory, stealing */
149 for (tmp = op->inv; tmp != NULL; tmp = next) 140 for (tmp = op->inv; tmp; tmp = next)
150 { 141 {
151 next = tmp->below; 142 next = tmp->below;
152 143
153 /* you can't steal worn items, starting items, wiz stuff, 144 /* you can't steal worn items, starting items, wiz stuff,
154 * innate abilities, or items w/o a type. Generally 145 * innate abilities, or items w/o a type. Generally
158 * future possible problems. -b.t. 149 * future possible problems. -b.t.
159 * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL 150 * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL
160 * already -b.t. 151 * already -b.t.
161 */ 152 */
162 153
163 if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) || QUERY_FLAG (tmp, FLAG_APPLIED) 154 if (QUERY_FLAG (tmp, FLAG_APPLIED)
164 || !(tmp->type) 155 || !tmp->type
165 || tmp->type == SPELL 156 || tmp->type == SPELL
166 || QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_STEAL) || tmp->invisible) 157 || QUERY_FLAG (tmp, FLAG_STARTEQUIP)
158 || QUERY_FLAG (tmp, FLAG_NO_STEAL)
159 || tmp->invisible)
167 continue; 160 continue;
168 161
169 /* Okay, try stealing this item. Dependent on dexterity of thief, 162 /* Okay, try stealing this item. Dependent on dexterity of thief,
170 * skill level, see the adj_stealroll fctn for more detail. 163 * skill level, see the adj_stealroll fctn for more detail.
171 */ 164 */
262 /* play_sound("stop! thief!"); kindofthing */ 255 /* play_sound("stop! thief!"); kindofthing */
263 } /* if you weren't 100% successful */ 256 } /* if you weren't 100% successful */
264 return success ? 1 : 0; 257 return success ? 1 : 0;
265} 258}
266 259
267
268int 260int
269steal (object *op, int dir, object *skill) 261steal (object *op, int dir, object *skill)
270{ 262{
271 object *tmp, *next; 263 object *tmp, *next;
272 sint16 x, y; 264 sint16 x, y;
808 new_draw_info (NDI_UNIQUE, 0, pl, "...and learn nothing more."); 800 new_draw_info (NDI_UNIQUE, 0, pl, "...and learn nothing more.");
809 } 801 }
810 return success; 802 return success;
811} 803}
812 804
813
814/* players using this skill can 'charm' a monster -- 805/* players using this skill can 'charm' a monster --
815 * into working for them. It can only be used on 806 * into working for them. It can only be used on
816 * non-special (see below) 'neutral' creatures. 807 * non-special (see below) 'neutral' creatures.
817 * -b.t. (thomas@astro.psu.edu) 808 * -b.t. (thomas@astro.psu.edu)
818 */ 809 */
819
820int 810int
821use_oratory (object *pl, int dir, object *skill) 811use_oratory (object *pl, int dir, object *skill)
822{ 812{
823 sint16 x = pl->x + freearr_x[dir], y = pl->y + freearr_y[dir]; 813 sint16 x = pl->x + freearr_x[dir], y = pl->y + freearr_y[dir];
824 int mflags, chance; 814 int mflags, chance;
914 tmp->stats.exp = 0; 904 tmp->stats.exp = 0;
915 add_friendly_object (tmp); 905 add_friendly_object (tmp);
916 tmp->attack_movement = PETMOVE; 906 tmp->attack_movement = PETMOVE;
917 return calc_skill_exp (pl, tmp, skill); 907 return calc_skill_exp (pl, tmp, skill);
918 } 908 }
909
919 /* Charm failed. Creature may be angry now */ 910 /* Charm failed. Creature may be angry now */
920 else if ((skill->level + ((pl->stats.Cha - 10) / 2)) < random_roll (1, 2 * tmp->level, pl, PREFER_LOW)) 911 else if ((skill->level + ((pl->stats.Cha - 10) / 2)) < random_roll (1, 2 * tmp->level, pl, PREFER_LOW))
921 { 912 {
922 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your speech angers the %s!\n", query_name (tmp)); 913 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your speech angers the %s!\n", query_name (tmp));
923 if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) 914 if (QUERY_FLAG (tmp, FLAG_FRIENDLY))
924 { 915 {
925 CLEAR_FLAG (tmp, FLAG_FRIENDLY); 916 CLEAR_FLAG (tmp, FLAG_FRIENDLY);
926 remove_friendly_object (tmp); 917 remove_friendly_object (tmp);
927 tmp->attack_movement = 0; /* needed? */ 918 tmp->attack_movement = 0; /* needed? */
928 } 919 }
920
929 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE); 921 CLEAR_FLAG (tmp, FLAG_UNAGGRESSIVE);
930 } 922 }
923
931 return 0; /* Fall through - if we get here, we didn't charm anything */ 924 return 0; /* Fall through - if we get here, we didn't charm anything */
932} 925}
933 926
934/* Singing() -this skill allows the player to pacify nearby creatures. 927/* Singing() -this skill allows the player to pacify nearby creatures.
935 * There are few limitations on who/what kind of 928 * There are few limitations on who/what kind of
1235} 1228}
1236 1229
1237/* write_note() - this routine allows players to inscribe messages in 1230/* write_note() - this routine allows players to inscribe messages in
1238 * ordinary 'books' (anything that is type BOOK). b.t. 1231 * ordinary 'books' (anything that is type BOOK). b.t.
1239 */ 1232 */
1240
1241static int 1233static int
1242write_note (object *pl, object *item, const char *msg, object *skill) 1234write_note (object *pl, object *item, const char *msg, object *skill)
1243{ 1235{
1244 char buf[1024]; 1236 char buf[1024];
1245 object *newBook = NULL; 1237 object *newBook = NULL;
1252 { 1244 {
1253 new_draw_info (NDI_UNIQUE, 0, pl, "No message to write!"); 1245 new_draw_info (NDI_UNIQUE, 0, pl, "No message to write!");
1254 new_draw_info_format (NDI_UNIQUE, 0, pl, "Usage: use_skill %s <message>", &skill->skill); 1246 new_draw_info_format (NDI_UNIQUE, 0, pl, "Usage: use_skill %s <message>", &skill->skill);
1255 return 0; 1247 return 0;
1256 } 1248 }
1249
1257 if (strcasestr_local (msg, "endmsg")) 1250 if (strcasestr_local (msg, "endmsg"))
1258 { 1251 {
1259 new_draw_info (NDI_UNIQUE, 0, pl, "Trying to cheat now are we?"); 1252 new_draw_info (NDI_UNIQUE, 0, pl, "Trying to cheat now are we?");
1260 return 0; 1253 return 0;
1261 } 1254 }
1287 /* This shouldn't be necessary - the object hasn't changed in any 1280 /* This shouldn't be necessary - the object hasn't changed in any
1288 * visible way 1281 * visible way
1289 */ 1282 */
1290 /* esrv_send_item(pl, item); */ 1283 /* esrv_send_item(pl, item); */
1291 } 1284 }
1285
1292 new_draw_info_format (NDI_UNIQUE, 0, pl, "You write in the %s.", query_short_name (item)); 1286 new_draw_info_format (NDI_UNIQUE, 0, pl, "You write in the %s.", query_short_name (item));
1293 return strlen (msg); 1287 return strlen (msg);
1294 } 1288 }
1295 else 1289 else
1296 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your message won't fit in the %s!", query_short_name (item)); 1290 new_draw_info_format (NDI_UNIQUE, 0, pl, "Your message won't fit in the %s!", query_short_name (item));
1316 new_draw_info (NDI_UNIQUE, 0, pl, "A spell can only be inscribed into a scroll!"); 1310 new_draw_info (NDI_UNIQUE, 0, pl, "A spell can only be inscribed into a scroll!");
1317 return 0; 1311 return 0;
1318 } 1312 }
1319 1313
1320 /* Check if we are ready to attempt inscription */ 1314 /* Check if we are ready to attempt inscription */
1321 chosen_spell = pl->contr->ranges[range_magic]; 1315 chosen_spell = pl->contr->ranged_ob;
1322 if (!chosen_spell) 1316 if (!chosen_spell || chosen_spell->type != SPELL)
1323 { 1317 {
1324 new_draw_info (NDI_UNIQUE, 0, pl, "You need a spell readied in order to inscribe!"); 1318 new_draw_info (NDI_UNIQUE, 0, pl, "You need a spell readied in order to inscribe!");
1325 return 0; 1319 return 0;
1326 } 1320 }
1321
1327 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_GRACE) > pl->stats.grace) 1322 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_GRACE) > pl->stats.grace)
1328 { 1323 {
1329 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough grace to write a scroll of %s.", &chosen_spell->name); 1324 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough grace to write a scroll of %s.", &chosen_spell->name);
1330 return 0; 1325 return 0;
1331 } 1326 }
1327
1332 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_MANA) > pl->stats.sp) 1328 if (SP_level_spellpoint_cost (pl, chosen_spell, SPELL_MANA) > pl->stats.sp)
1333 { 1329 {
1334 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough mana to write a scroll of %s.", &chosen_spell->name); 1330 new_draw_info_format (NDI_UNIQUE, 0, pl, "You don't have enough mana to write a scroll of %s.", &chosen_spell->name);
1335 return 0; 1331 return 0;
1336 } 1332 }
1361 newscroll = scroll->clone (); 1357 newscroll = scroll->clone ();
1362 decrease_ob (scroll); 1358 decrease_ob (scroll);
1363 newscroll->nrof = 1; 1359 newscroll->nrof = 1;
1364 } 1360 }
1365 else 1361 else
1366 {
1367 newscroll = scroll; 1362 newscroll = scroll;
1368 }
1369 1363
1370 if (!confused) 1364 if (!confused)
1371 { 1365 {
1372 newscroll->level = MAX (skill->level, chosen_spell->level); 1366 newscroll->level = MAX (skill->level, chosen_spell->level);
1373 new_draw_info (NDI_UNIQUE, 0, pl, "You succeed in writing a new scroll."); 1367 new_draw_info (NDI_UNIQUE, 0, pl, "You succeed in writing a new scroll.");
1399 { 1393 {
1400 /* Remove to correctly merge with other items which may exist in inventory */ 1394 /* Remove to correctly merge with other items which may exist in inventory */
1401 newscroll->remove (); 1395 newscroll->remove ();
1402 esrv_del_item (pl->contr, newscroll->count); 1396 esrv_del_item (pl->contr, newscroll->count);
1403 } 1397 }
1398
1404 newscroll = insert_ob_in_ob (newscroll, pl); 1399 newscroll = insert_ob_in_ob (newscroll, pl);
1405 esrv_send_item (pl, newscroll); 1400 esrv_send_item (pl, newscroll);
1406 success = calc_skill_exp (pl, newscroll, skill); 1401 success = calc_skill_exp (pl, newscroll, skill);
1407 if (!confused) 1402 if (!confused)
1408 success *= 2; 1403 success *= 2;
1451 if (!params) 1446 if (!params)
1452 { 1447 {
1453 params = ""; 1448 params = "";
1454 string = params; 1449 string = params;
1455 } 1450 }
1451
1456 skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY); 1452 skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY);
1457 1453
1458 /* Need to be able to read before we can write! */ 1454 /* Need to be able to read before we can write! */
1459 if (!find_skill_by_name (pl, skat->clone.skill)) 1455 if (!find_skill_by_name (pl, skat->clone.skill))
1460 { 1456 {
1484 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no %s to write on", msgtype == BOOK ? "book" : "scroll"); 1480 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no %s to write on", msgtype == BOOK ? "book" : "scroll");
1485 return 0; 1481 return 0;
1486 } 1482 }
1487 1483
1488 if (msgtype == SCROLL) 1484 if (msgtype == SCROLL)
1489 {
1490 return write_scroll (pl, item, skill); 1485 return write_scroll (pl, item, skill);
1491 }
1492 else if (msgtype == BOOK) 1486 else if (msgtype == BOOK)
1493 {
1494 return write_note (pl, item, string, skill); 1487 return write_note (pl, item, string, skill);
1495 } 1488
1496 return 0; 1489 return 0;
1497} 1490}
1498
1499
1500 1491
1501/* find_throw_ob() - if we request an object, then 1492/* find_throw_ob() - if we request an object, then
1502 * we search for it in the inventory of the owner (you've 1493 * we search for it in the inventory of the owner (you've
1503 * got to be carrying something in order to throw it!). 1494 * got to be carrying something in order to throw it!).
1504 * If we didnt request an object, then the top object in inventory 1495 * If we didnt request an object, then the top object in inventory
1505 * (that is "throwable", ie no throwing your skills away!) 1496 * (that is "throwable", ie no throwing your skills away!)
1506 * is the object of choice. Also check to see if object is 1497 * is the object of choice. Also check to see if object is
1507 * 'throwable' (ie not applied cursed obj, worn, etc). 1498 * 'throwable' (ie not applied cursed obj, worn, etc).
1508 */ 1499 */
1509
1510static object * 1500static object *
1511find_throw_ob (object *op, const char *request) 1501find_throw_ob (object *op, const char *request)
1512{ 1502{
1513 object *tmp; 1503 object *tmp;
1514 1504
1586 1576
1587/* make_throw_ob() We construct the 'carrier' object in 1577/* make_throw_ob() We construct the 'carrier' object in
1588 * which we will insert the object that is being thrown. 1578 * which we will insert the object that is being thrown.
1589 * This combination becomes the 'thrown object'. -b.t. 1579 * This combination becomes the 'thrown object'. -b.t.
1590 */ 1580 */
1591
1592static object * 1581static object *
1593make_throw_ob (object *orig) 1582make_throw_ob (object *orig)
1594{ 1583{
1595 if (!orig) 1584 if (!orig)
1596 return NULL; 1585 return NULL;
1609 toss_item->stats.dam = 0; /* default damage */ 1598 toss_item->stats.dam = 0; /* default damage */
1610 insert_ob_in_ob (orig, toss_item); 1599 insert_ob_in_ob (orig, toss_item);
1611 return toss_item; 1600 return toss_item;
1612} 1601}
1613 1602
1614
1615/* do_throw() - op throws any object toss_item. This code 1603/* do_throw() - op throws any object toss_item. This code
1616 * was borrowed from fire_bow. 1604 * was borrowed from fire_bow.
1617 * Returns 1 if skill was successfully used, 0 if not 1605 * Returns 1 if skill was successfully used, 0 if not
1618 */ 1606 */
1619
1620static int 1607static int
1621do_throw (object *op, object *part, object *toss_item, int dir, object *skill) 1608do_throw (object *op, object *part, object *toss_item, int dir, object *skill)
1622{ 1609{
1623 object *throw_ob = toss_item, *left = NULL; 1610 object *throw_ob = toss_item, *left = NULL;
1624 int eff_str = 0, maxc, str = op->stats.Str, dam = 0; 1611 int eff_str = 0, maxc, str = op->stats.Str, dam = 0;
1793 if (GET_ANIM_ID (throw_ob) && NUM_ANIMATIONS (throw_ob)) 1780 if (GET_ANIM_ID (throw_ob) && NUM_ANIMATIONS (throw_ob))
1794 SET_ANIMATION (throw_ob, dir); 1781 SET_ANIMATION (throw_ob, dir);
1795 } 1782 }
1796 else 1783 else
1797 { 1784 {
1785 uint16 mat = throw_ob->materials;
1786
1798 /* some materials will adjust properties.. */ 1787 /* some materials will adjust properties.. */
1799 if (throw_ob->material & M_LEATHER) 1788 if (mat & M_LEATHER)
1800 { 1789 {
1801 throw_ob->stats.dam -= 1; 1790 throw_ob->stats.dam -= 1;
1802 throw_ob->stats.food -= 10; 1791 throw_ob->stats.food -= 10;
1803 } 1792 }
1804 1793
1805 if (throw_ob->material & M_GLASS) 1794 if (mat & M_GLASS)
1806 throw_ob->stats.food += 60; 1795 throw_ob->stats.food += 60;
1807 1796
1808 if (throw_ob->material & M_ORGANIC) 1797 if (mat & M_ORGANIC)
1809 { 1798 {
1810 throw_ob->stats.dam -= 3; 1799 throw_ob->stats.dam -= 3;
1811 throw_ob->stats.food += 55; 1800 throw_ob->stats.food += 55;
1812 } 1801 }
1813 1802
1814 if (throw_ob->material & M_PAPER || throw_ob->material & M_CLOTH) 1803 if (mat & M_PAPER || mat & M_CLOTH)
1815 { 1804 {
1816 throw_ob->stats.dam -= 5; 1805 throw_ob->stats.dam -= 5;
1817 throw_ob->speed *= 0.8; 1806 throw_ob->speed *= 0.8;
1818 throw_ob->stats.wc += 3; 1807 throw_ob->stats.wc += 3;
1819 throw_ob->stats.food -= 30; 1808 throw_ob->stats.food -= 30;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines