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

Comparing deliantra/server/server/c_object.C (file contents):
Revision 1.107 by elmex, Fri Nov 13 15:41:39 2009 UTC vs.
Revision 1.119 by root, Sat Apr 10 04:54:09 2010 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 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 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.
25/* 25/*
26 * Object (handling) commands 26 * Object (handling) commands
27 */ 27 */
28 28
29#include <global.h> 29#include <global.h>
30#include <loader.h>
31#include <skills.h> 30#include <skills.h>
32#include <sproto.h> 31#include <sproto.h>
33#include <living.h> 32#include <living.h>
34 33
35/* 34/*
137 136
138 skill = find_skill_by_name_fuzzy (pl, params); 137 skill = find_skill_by_name_fuzzy (pl, params);
139 138
140 if (!skill) 139 if (!skill)
141 { 140 {
142 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the skill %s", params); 141 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the %s skill.", params);
143 return 0; 142 return 0;
144 } 143 }
145 144
146 pl->change_skill (0); 145 pl->apply (skill);
147 apply_special (pl, skill, AP_APPLY);
148 return 1; 146 return 1;
149} 147}
150 148
151/* A little special because we do want to pass the full params along 149/* A little special because we do want to pass the full params along
152 * as it includes the object to throw. 150 * as it includes the object to throw.
155command_throw (object *op, char *params) 153command_throw (object *op, char *params)
156{ 154{
157 if (object *skop = find_skill_by_name (op, skill_names[SK_THROWING])) 155 if (object *skop = find_skill_by_name (op, skill_names[SK_THROWING]))
158 return do_skill (op, op, skop, op->facing, params); 156 return do_skill (op, op, skop, op->facing, params);
159 else 157 else
160 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the skill throwing."); 158 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the throwing skill.");
161 159
162 return 0; 160 return 0;
163} 161}
164 162
165int 163int
191 189
192 while (*params == ' ') 190 while (*params == ' ')
193 params++; 191 params++;
194 192
195 if (object *inv = find_best_apply_object_match (op, params, aflag)) 193 if (object *inv = find_best_apply_object_match (op, params, aflag))
196 player_apply (op, inv, aflag, 0); 194 op->apply (inv, aflag);
197 else 195 else
198 new_draw_info_format (NDI_UNIQUE, 0, op, "Could not find any match to the %s.", params); 196 op->failmsgf ("Could not find any match to the %s.", params);
199 } 197 }
200 198
201 return 0; 199 return 0;
202} 200}
203 201
225 return 0; 223 return 0;
226 } 224 }
227 225
228 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) 226 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type)))
229 { 227 {
230 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can put only %s into the %s.", &sack->race, query_name (sack)); 228 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can only put objects of type '%s' into the %s.", &sack->race, query_name (sack));
231 return 0; 229 return 0;
232 } 230 }
233 231
234 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) 232 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying)
235 { 233 {
558 */ 556 */
559 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof))) 557 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof)))
560 return; 558 return;
561 559
562 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 560 if (QUERY_FLAG (tmp, FLAG_APPLIED))
563 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 561 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
564 return; 562 return;
565 563
566 /* we want to put some portion of the item into the container */ 564 /* we want to put some portion of the item into the container */
567 if (!can_split (op, tmp, nrof)) 565 if (!can_split (op, tmp, nrof))
568 return; 566 return;
607 return; 605 return;
608 606
609 if (obj->destroyed () || obj->is_inserted ()) 607 if (obj->destroyed () || obj->is_inserted ())
610 return; 608 return;
611 609
612 if (is_in_shop (dropper) && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY) 610 if (dropper->is_in_shop () && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY)
613 if (!sell_item (obj, dropper)) 611 if (!sell_item (obj, dropper))
614 return; 612 return;
615 613
616 if (!obj->can_drop_at (dropper->map, dropper->x, dropper->y, dropper)) 614 if (!obj->can_drop_at (dropper->map, dropper->x, dropper->y, dropper))
617 return; 615 return;
637{ 635{
638 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 636 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
639 return; 637 return;
640 638
641 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 639 if (QUERY_FLAG (tmp, FLAG_APPLIED))
642 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 640 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
643 return; /* can't unapply it */ 641 return; /* can't unapply it */
644 642
645 /* We are only dropping some of the items. We split the current object 643 /* We are only dropping some of the items. We split the current object
646 * off 644 * off
647 */ 645 */
1104{ 1102{
1105 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ()); 1103 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ());
1106} 1104}
1107 1105
1108static void 1106static void
1109describe_dump_object (dynbuf &buf, object *ob)
1110{
1111 char *txt = dump_object (ob);
1112 for (char *p = txt; *p; ++p) if (*p == '\n') *p = '\r';
1113 buf << "\n" << txt << "\n";
1114
1115 if (!ob->is_arch ())
1116 describe_dump_object (buf, ob->arch);
1117}
1118
1119std::string
1120object::describe (object *who)
1121{
1122 dynbuf_text buf (1024, 1024);
1123
1124 buf.printf ("That is: %s.\r", long_desc (who).c_str ());
1125
1126 if (custom_name)
1127 buf.printf ("You call it %s.\r", &custom_name);
1128
1129 switch (type)
1130 {
1131 case SPELLBOOK:
1132 if (flag [FLAG_IDENTIFIED] && inv)
1133 buf.printf ("%s is a level %s %s spell.\r", &inv->name, get_levelnumber (inv->level), &inv->skill);
1134 break;
1135
1136 case BOOK:
1137 if (msg)
1138 buf << "Something is written in it.\r";
1139 break;
1140
1141 case CONTAINER:
1142 if (race)
1143 {
1144 if (weight_limit && stats.Str < 100)
1145 buf.printf ("It can hold only %s and its weight limit is %.1f kg.\r",
1146 &race, weight_limit / (10.0 * (100 - stats.Str)));
1147 else
1148 buf.printf ("It can hold only %s.\r", &race);
1149 }
1150 else if (weight_limit && stats.Str < 100)
1151 buf.printf ("Its weight limit is %.1f kg.\r", weight_limit / (10.0 * (100 - stats.Str)));
1152 break;
1153
1154 case WAND:
1155 if (flag [FLAG_IDENTIFIED])
1156 buf.printf ("It has %d charges left.\r", stats.food);
1157 break;
1158 }
1159
1160 if (material != MATERIAL_NULL && !msg)
1161 buf << (nrof > 1 ? "They are made of " : "It is made of ")
1162 << material->description
1163 << ".\r";
1164
1165 if (who)
1166 /* Where to wear this item */
1167 for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1168 if (slot[i].info)
1169 {
1170 buf << (who->slot[i].info ? body_locations[i].use_name : body_locations[i].nonuse_name);
1171
1172 if (slot[i].info < -1 && who->slot[i].info)
1173 buf.printf ("(%d)", -slot[i].info);
1174
1175 buf << ".\r";
1176 }
1177
1178 if (weight)
1179 buf.printf ("%s %3.3f kg.\r", nrof > 1 ? "They weigh" : "It weighs", weight * (nrof ? nrof : 1) / 1000.0);
1180
1181 if (flag [FLAG_STARTEQUIP])
1182 buf << (nrof > 1 ? "They were" : "It was")
1183 << " given by a god and will vanish when dropped.\r";
1184
1185 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1186 {
1187 buf.printf ("You reckon %s worth %s.\r", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1188
1189 if (is_in_shop (who))
1190 {
1191 if (flag [FLAG_UNPAID])
1192 buf.printf ("%s would cost you %s.\r", nrof > 1 ? "They" : "It", query_cost_string (this, who, F_BUY | F_SHOP));
1193 else
1194 buf.printf ("You are offered %s for %s.\r", query_cost_string (this, who, F_SELL + F_SHOP), nrof > 1 ? "them" : "it");
1195 }
1196 }
1197
1198 if (flag [FLAG_MONSTER])
1199 buf << describe_monster (who);
1200
1201 /* Is this item buildable? */
1202 if (flag [FLAG_IS_BUILDABLE])
1203 buf << "This is a buildable item.\r";
1204
1205 /* Does the object have a message? Don't show message for all object
1206 * types - especially if the first entry is a match
1207 */
1208 if (msg)
1209 {
1210 if (type != EXIT && type != BOOK && type != CORPSE && !move_on && !has_dialogue ())
1211 {
1212 buf << '\r';
1213
1214 /* This is just a hack so when identifying the items, we print
1215 * out the extra message
1216 */
1217 if (need_identify (this) && flag [FLAG_IDENTIFIED])
1218 buf << "The object has a story:\r";
1219
1220 buf << msg << '\n';
1221 }
1222 }
1223 else if (inv && inv->type == SPELL && flag [FLAG_IDENTIFIED]
1224 && (type == SPELLBOOK || type == ROD || type == WAND
1225 || type == ROD || type == POTION || type == SCROLL))
1226 // for spellbooks and other stuff that contains spells, print the spell message,
1227 // unless the object has a custom message handled above.
1228 buf << '\r' << inv->msg << '\n';
1229
1230 // try to display the duration for some potions and scrolls
1231 // this includes change ability potions and group spells,
1232 // but does not handle protection potions
1233 if (inv && inv->type == SPELL && flag [FLAG_IDENTIFIED]
1234 && (type == POTION || type == SCROLL))
1235 {
1236 object *spell = inv;
1237
1238 if (spell->subtype == SP_PARTY_SPELL)
1239 spell = spell->other_arch;
1240
1241 if (spell->subtype == SP_CHANGE_ABILITY)
1242 buf.printf ("\nH<The effect will last about %.10g seconds.>",
1243 TICK2TIME (change_ability_duration (spell, this)));
1244 }
1245
1246 // Display a hint about inscribable items [empty books]
1247 // This includes the amount of text they can hold.
1248 if (type == INSCRIBABLE)
1249 {
1250 if (other_arch && other_arch->type == SCROLL)
1251 buf.printf ("\nH<You can use the inscription skill to inscribe a spell into it.>");
1252 else
1253 buf.printf ("\nH<You can use the inscription skill to inscribe text into it. It has room for up to %d characters.>",
1254 weight_limit);
1255 }
1256
1257 buf << '\n';
1258
1259 // the dungeon master additionally gets a complete dump
1260 if (who && who->flag [FLAG_WIZLOOK])
1261 {
1262 buf << "\nT<Object>\n";
1263 describe_dump_object (buf, this);
1264
1265 if (inv)
1266 {
1267 buf << "\nT<Top Inventory>\n";
1268 describe_dump_object (buf, inv);
1269 }
1270 }
1271
1272 return std::string (buf.linearise (), buf.size ());
1273}
1274
1275static void
1276display_new_pickup (object *op) 1107display_new_pickup (object *op)
1277{ 1108{
1278 int i = op->contr->mode; 1109 int i = op->contr->mode;
1279 1110
1280 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0); 1111 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0);
1472 esrv_update_item (UPD_FLAGS, op, item); 1303 esrv_update_item (UPD_FLAGS, op, item);
1473 } 1304 }
1474 1305
1475 return 0; 1306 return 0;
1476} 1307}
1308
1309/* op should be a player, params is any params.
1310 * If no params given, we print out the currently marked object.
1311 * otherwise, try to find a matching object - try best match first.
1312 */
1313int
1314command_mark (object *op, char *params)
1315{
1316 if (!params)
1317 {
1318 if (object *mark = find_marked_object (op))
1319 op->statusmsg (format ("%s is marked.", query_name (mark)));
1320 else
1321 op->failmsg ("You have no marked object.");
1322 }
1323 else
1324 {
1325 if (object *mark = find_best_object_match (op, params))
1326 {
1327 op->contr->mark = mark;
1328 op->statusmsg (format ("Marked item %s", query_name (mark)));
1329 }
1330 else
1331 op->failmsgf ("Could not find an object that matches %s", params);
1332 }
1333
1334 return 0; /*shouldnt get here */
1335}
1336

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines