/* ************************************************************************
* File: act.obj1.c Part of CircleMUD *
* Usage: object handling routines -- get/drop and container handling *
* *
* All rights reserved. See license.doc for complete information. *
* *
* Copyright (C) 1993 by the Trustees of the Johns Hopkins University *
* CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. *
************************************************************************ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#include "spells.h"
/* extern variables */
extern struct str_app_type str_app[];
extern struct room_data *world;
void perform_put(struct char_data *ch, struct obj_data *obj,
struct obj_data *container)
{
if (GET_OBJ_WEIGHT(container) + GET_OBJ_WEIGHT(obj) > container->obj_flags.value[0])
act("$p won't fit in $P.", FALSE, ch, obj, container, TO_CHAR);
else {
obj_from_char(obj);
obj_to_obj(obj, container);
act("You put $p in $P.", FALSE, ch, obj, container, TO_CHAR);
act("$n puts $p in $P.", TRUE, ch, obj, container, TO_ROOM);
}
}
/* The following put modes are supported by the code below:
1) put <object> <container>
2) put all.<object> <container>
3) put all <container>
<container> must be in inventory or on ground.
all objects to be put into container must be in inventory.
*/
ACMD(do_put)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
struct obj_data *obj;
struct obj_data *next_obj;
struct obj_data *container;
struct char_data *tmp_char;
int obj_dotmode, cont_dotmode;
argument_interpreter(argument, arg1, arg2);
obj_dotmode = find_all_dots(arg1);
cont_dotmode = find_all_dots(arg2);
if (cont_dotmode != FIND_INDIV)
send_to_char("You can only put things into one container at a time.\n\r", ch);
else if (!*arg1)
send_to_char("Put what in what?\n\r", ch);
else if (!*arg2) {
sprintf(buf, "What do you want to put %s in?\n\r",
((obj_dotmode != FIND_INDIV) ? "them" : "it"));
send_to_char(buf, ch);
} else {
generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &container);
if (!container) {
sprintf(buf, "You don't see a %s here.\n\r", arg2);
send_to_char(buf, ch);
} else if (GET_ITEM_TYPE(container) != ITEM_CONTAINER) {
act("$p is not a container.", FALSE, ch, container, 0, TO_CHAR);
} else if (IS_SET(container->obj_flags.value[1], CONT_CLOSED)) {
send_to_char("You'd better open it first!\n\r", ch);
} else {
if (obj_dotmode == FIND_ALL) { /* "put all <container>" case */
/* check and make sure the guy has something first */
if (container == ch->carrying && !ch->carrying->next_content)
send_to_char("You don't seem to have anything to put in it.\n\r", ch);
else for (obj = ch->carrying; obj; obj = next_obj) {
next_obj = obj->next_content;
if (obj != container)
perform_put(ch, obj, container);
}
} else if (obj_dotmode == FIND_ALLDOT) { /* "put all.x <cont>" case */
if (!(obj = get_obj_in_list_vis(ch, arg1, ch->carrying))) {
sprintf(buf, "You don't seem to have any %ss.\n\r", arg1);
send_to_char(buf, ch);
} else while (obj) {
next_obj = get_obj_in_list_vis(ch, arg1, obj->next_content);
if (obj != container)
perform_put(ch, obj, container);
obj = next_obj;
}
} else { /* "put <thing> <container>" case */
if (!(obj = get_obj_in_list_vis(ch, arg1, ch->carrying))) {
sprintf(buf, "You aren't carrying %s %s.\n\r", AN(arg1), arg1);
send_to_char(buf, ch);
} else if (obj == container)
send_to_char("You attempt to fold it into itself, but fail.\n\r", ch);
else
perform_put(ch, obj, container);
}
}
}
}
int can_take_obj(struct char_data *ch, struct obj_data *obj)
{
if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) {
sprintf(buf, "%s: You can't carry that many items.\n\r", OBJS(obj, ch));
send_to_char(buf, ch);
return 0;
} else if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) {
sprintf(buf, "%s: You can't carry that much weight.\n\r", OBJS(obj, ch));
send_to_char(buf, ch);
return 0;
} else if (!(CAN_WEAR(obj, ITEM_TAKE))) {
sprintf(buf, "%s: You can't take that!\n\r", OBJS(obj, ch));
send_to_char(buf, ch);
return 0;
}
return 1;
}
void get_check_money(struct char_data *ch, struct obj_data *obj)
{
if ((GET_ITEM_TYPE(obj) == ITEM_MONEY) && (obj->obj_flags.value[0] > 0)) {
obj_from_char(obj);
if (obj->obj_flags.value[0] > 1) {
sprintf(buf, "There were %d coins.\n\r", obj->obj_flags.value[0]);
send_to_char(buf, ch);
}
GET_GOLD(ch) += obj->obj_flags.value[0];
extract_obj(obj);
}
}
void perform_get_from_container(struct char_data *ch, struct obj_data *obj,
struct obj_data *cont, int mode)
{
if (mode == FIND_OBJ_INV || can_take_obj(ch, obj)) {
if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch))
sprintf(buf, "%s: You can't hold any more items.\n\r", OBJS(obj, ch));
else {
obj_from_obj(obj);
obj_to_char(obj, ch);
act("You get $p from $P.", FALSE, ch, obj, cont, TO_CHAR);
act("$n gets $p from $P.", TRUE, ch, obj, cont, TO_ROOM);
get_check_money(ch, obj);
}
}
}
void get_from_container(struct char_data *ch, struct obj_data *cont,
char *arg, int mode)
{
struct obj_data *obj, *next_obj;
int obj_dotmode, found = 0;
obj_dotmode = find_all_dots(arg);
if (IS_SET(cont->obj_flags.value[1], CONT_CLOSED))
act("The $p is closed.", FALSE, ch, cont, 0, TO_CHAR);
else if (obj_dotmode == FIND_ALL) {
for (obj = cont->contains; obj; obj = next_obj) {
next_obj = obj->next_content;
if (CAN_SEE_OBJ(ch, obj)) {
found = 1;
perform_get_from_container(ch, obj, cont, mode);
}
}
if (!found)
act("$p seems to be empty.", FALSE, ch, cont, 0, TO_CHAR);
} else if (obj_dotmode == FIND_ALLDOT) {
if (!*arg) {
send_to_char("Get all of what?\n\r", ch);
return;
}
obj = get_obj_in_list_vis(ch, arg, cont->contains);
while (obj) {
next_obj = get_obj_in_list_vis(ch, arg, obj->next_content);
if (CAN_SEE_OBJ(ch, obj)) {
found = 1;
perform_get_from_container(ch, obj, cont, mode);
}
obj = next_obj;
}
if (!found) {
sprintf(buf, "You can't find any %ss in $p.", arg);
act(buf, FALSE, ch, cont, 0, TO_CHAR);
}
} else {
if (!(obj = get_obj_in_list_vis(ch, arg, cont->contains))) {
sprintf(buf, "There doesn't seem to be %s %s in $p.", AN(arg), arg);
act(buf, FALSE, ch, cont, 0, TO_CHAR);
} else
perform_get_from_container(ch, obj, cont, mode);
}
}
int perform_get_from_room(struct char_data *ch, struct obj_data *obj)
{
if (can_take_obj(ch, obj)) {
obj_from_room(obj);
obj_to_char(obj, ch);
act("You get $p.", FALSE, ch, obj, 0, TO_CHAR);
act("$n gets $p.", TRUE, ch, obj, 0, TO_ROOM);
get_check_money(ch, obj);
return 1;
}
return 0;
}
void get_from_room(struct char_data *ch, char *arg)
{
struct obj_data *obj, *next_obj;
int dotmode, found = 0;
dotmode = find_all_dots(arg);
if (dotmode == FIND_ALL) {
for (obj = world[ch->in_room].contents; obj; obj = next_obj) {
next_obj = obj->next_content;
if (CAN_SEE_OBJ(ch, obj)) {
found = 1;
perform_get_from_room(ch, obj);
}
}
if (!found)
send_to_char("There doesn't seem to be anything here.\n\r", ch);
} else if (dotmode == FIND_ALLDOT) {
if (!*arg) {
send_to_char("Get all of what?\n\r", ch);
return;
}
if (!(obj = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) {
sprintf(buf, "You don't see any %ss here.\n\r", arg);
send_to_char(buf, ch);
} else while (obj) {
next_obj = get_obj_in_list_vis(ch, arg, obj->next_content);
perform_get_from_room(ch, obj);
obj = next_obj;
}
} else {
if (!(obj = get_obj_in_list_vis(ch, arg, world[ch->in_room].contents))) {
sprintf(buf, "You don't see %s %s here.\n\r", AN(arg), arg);
send_to_char(buf, ch);
} else
perform_get_from_room(ch, obj);
}
}
ACMD(do_get)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int cont_dotmode, found = 0, mode;
struct obj_data *cont, *next_cont;
struct char_data *tmp_char;
if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch))
send_to_char("Your arms are already full!\n\r", ch);
else {
argument_interpreter(argument, arg1, arg2);
if (!*arg1)
send_to_char("Get what?\n\r", ch);
else {
if (!*arg2)
get_from_room(ch, arg1);
else {
cont_dotmode = find_all_dots(arg2);
if (cont_dotmode == FIND_ALL) { /* use all in inv. and on ground */
for(cont = ch->carrying; cont; cont = cont->next_content)
if (GET_ITEM_TYPE(cont) == ITEM_CONTAINER) {
found = 1;
get_from_container(ch, cont, arg1, FIND_OBJ_INV);
}
for(cont = world[ch->in_room].contents; cont; cont = cont->next_content)
if (CAN_SEE_OBJ(ch, cont) && GET_ITEM_TYPE(cont) == ITEM_CONTAINER) {
found = 1;
get_from_container(ch, cont, arg1, FIND_OBJ_ROOM);
}
if (!found)
send_to_char("You can't seem to find any containers.\n\r", ch);
} else if (cont_dotmode == FIND_ALLDOT) {
if (!*arg2) {
send_to_char("Get from all of what?\n\r", ch);
return;
}
cont = get_obj_in_list_vis(ch, arg2, ch->carrying);
while (cont) {
found = 1;
next_cont = get_obj_in_list_vis(ch, arg2, cont->next_content);
if (GET_ITEM_TYPE(cont) != ITEM_CONTAINER)
act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
else
get_from_container(ch, cont, arg1, FIND_OBJ_INV);
cont = next_cont;
}
cont = get_obj_in_list_vis(ch, arg2, world[ch->in_room].contents);
while (cont) {
found = 1;
next_cont = get_obj_in_list_vis(ch, arg2, cont->next_content);
if (GET_ITEM_TYPE(cont) != ITEM_CONTAINER)
act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
else
get_from_container(ch, cont, arg1, FIND_OBJ_ROOM);
cont = next_cont;
}
if (!found) {
sprintf(buf, "You can't seem to find any %ss here.\n\r", arg2);
send_to_char(buf, ch);
}
} else { /* get <items> <container> (no all or all.x) */
mode = generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &cont);
if (!cont) {
sprintf(buf, "You don't have %s %s.\n\r", AN(arg2), arg2);
send_to_char(buf, ch);
} else if (GET_ITEM_TYPE(cont) != ITEM_CONTAINER)
act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR);
else
get_from_container(ch, cont, arg1, mode);
}
}
}
}
}
void perform_drop_gold(struct char_data *ch, int amount,
byte mode, sh_int RDR)
{
struct obj_data *obj;
if (amount <= 0)
send_to_char("Heh heh heh.. we are jolly funny today, eh?\n\r", ch);
else if (GET_GOLD(ch) < amount)
send_to_char("You don't have that many coins!\n\r", ch);
else {
if (mode != SCMD_JUNK) {
obj = create_money(amount);
if (mode == SCMD_DONATE) {
send_to_char("You throw some gold into the air where it disappears in a puff of smoke!\n\r", ch);
act("$n throws some gold into the air where it disappears in a puff of smoke!", FALSE, ch, 0, 0, TO_ROOM);
send_to_room("Some gold suddenly appears in mid-air, then drops to the ground!\n\r", RDR);
obj_to_room(obj, RDR);
} else {
send_to_char("You drop some gold.\n\r", ch);
act("$n drops some gold.", FALSE, ch, 0, 0, TO_ROOM);
obj_to_room(obj, ch->in_room);
}
} else {
act("$n drops some gold which disappears in a puff of smoke!", FALSE, ch, 0, 0, TO_ROOM);
send_to_char("You drop some gold which disappears in a puff of smoke!\n\r", ch);
}
GET_GOLD(ch) -= amount;
}
}
#define VANISH(mode) ((mode == SCMD_DONATE || mode == SCMD_JUNK) ? \
" It vanishes in a puff of smoke!" : "")
int perform_drop(struct char_data *ch, struct obj_data *obj,
byte mode, char *sname, sh_int RDR)
{
int value;
if (IS_SET(obj->obj_flags.extra_flags, ITEM_NODROP)) {
sprintf(buf, "You can't %s %s, it must be CURSED!\n\r", sname, OBJS(obj, ch));
send_to_char(buf, ch);
return 0;
}
if ((mode == SCMD_DONATE) && IS_SET(obj->obj_flags.extra_flags, ITEM_NODONATE)) {
sprintf(buf, "You can't donate %s.\n\r", OBJS(obj, ch));
send_to_char(buf, ch);
return 0;
}
sprintf(buf, "You %s %s.%s\n\r", sname, OBJS(obj, ch), VANISH(mode));
send_to_char(buf, ch);
sprintf(buf, "$n %ss $p.%s", sname, VANISH(mode));
act(buf, TRUE, ch, obj, 0, TO_ROOM);
obj_from_char(obj);
switch(mode) {
case SCMD_DROP:
obj_to_room(obj, ch->in_room);
return 0;
break;
case SCMD_DONATE:
obj_to_room(obj, RDR);
send_to_room("Something suddenly appears in a puff a smoke!\n\r", RDR);
return 0;
break;
case SCMD_JUNK:
value = MAX(1, MIN(200, obj->obj_flags.cost >> 4));
extract_obj(obj);
return value;
break;
default:
log("SYSERR: Incorrect argument passed to perform_drop");
break;
}
return 0;
}
ACMD(do_drop)
{
extern sh_int donation_room_1, donation_room_2, donation_room_3;
struct obj_data *obj, *next_obj;
sh_int RDR = 0;
byte mode = SCMD_DROP;
int dotmode, amount = 0;
char *sname;
switch (subcmd) {
case SCMD_JUNK:
sname = "junk";
mode = SCMD_JUNK;
break;
case SCMD_DONATE:
sname = "donate";
mode = SCMD_DONATE;
switch (number(0, 2)) {
case 0:
mode = SCMD_JUNK;
break;
case 1:
case 2: RDR = real_room(donation_room_1); break;
/* case 3: RDR = real_room(donation_room_2); break;
case 4: RDR = real_room(donation_room_3); break;
*/
}
if (RDR == NOWHERE) {
send_to_char("Sorry, you can't donate anything right now.\n\r", ch);
return;
}
break;
default:
sname = "drop";
break;
}
argument = one_argument(argument, arg);
if (!*arg) {
sprintf(buf, "What do you want to %s?\n\r", sname);
send_to_char(buf, ch);
return;
} else if (is_number(arg)) {
amount = atoi(arg);
argument = one_argument(argument, arg);
if (!str_cmp("coins", arg) || !str_cmp("coin", arg))
perform_drop_gold(ch, amount, mode, RDR);
else {
/* code to drop multiple items. anyone want to write it? -je */
send_to_char("Sorry, you can't do that (yet)...\n\r", ch);
return;
}
} else {
dotmode = find_all_dots(arg);
/* Can't junk or donate all */
if ((dotmode == FIND_ALL) && (subcmd == SCMD_JUNK || subcmd == SCMD_DONATE)) {
if (subcmd == SCMD_JUNK)
send_to_char("Go to the dump if you want to junk EVERYTHING!\n\r", ch);
else
send_to_char("Go do the donation room if you want to donate EVERYTHING!\n\r", ch);
return;
}
if (dotmode == FIND_ALL) {
if (!ch->carrying)
send_to_char("You don't seem to be carrying anything.\n\r", ch);
else
for (obj = ch->carrying; obj; obj = next_obj) {
next_obj = obj->next_content;
amount += perform_drop(ch, obj, mode, sname, RDR);
}
} else if (dotmode == FIND_ALLDOT) {
if (!*arg) {
sprintf(buf, "What do you want to %s all of?\n\r", sname);
send_to_char(buf, ch);
return;
}
if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) {
sprintf(buf, "You don't seem to have any %ss.\n\r", arg);
send_to_char(buf, ch);
}
while (obj) {
next_obj = get_obj_in_list_vis(ch, arg, obj->next_content);
amount += perform_drop(ch, obj, mode, sname, RDR);
obj = next_obj;
}
} else {
if (!(obj = get_obj_in_list_vis(ch, arg, ch->carrying))) {
sprintf(buf, "You don't seem to have %s %s.\n\r", AN(arg), arg);
send_to_char(buf, ch);
} else
amount += perform_drop(ch, obj, mode, sname, RDR);
}
}
if (amount && (subcmd == SCMD_JUNK)) {
send_to_char("You have been rewarded by the gods!\n\r", ch);
act("$n has been rewarded by the gods!", TRUE, ch, 0, 0, TO_ROOM);
GET_GOLD(ch) += amount;
}
}
void perform_give(struct char_data *ch, struct char_data *vict,
struct obj_data *obj)
{
if (IS_SET(obj->obj_flags.extra_flags, ITEM_NODROP)) {
act("You can't let go of $p!! Yeech!", FALSE, ch, obj, 0, TO_CHAR);
return;
}
if (IS_CARRYING_N(vict) >= CAN_CARRY_N(vict)) {
act("$N seems to have $S hands full.", FALSE, ch, 0, vict, TO_CHAR);
return;
}
if (GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(vict) > CAN_CARRY_W(vict)) {
act("$E can't carry that much weight.", FALSE, ch, 0, vict, TO_CHAR);
return;
}
obj_from_char(obj);
obj_to_char(obj, vict);
act("You give $p to $N.", FALSE, ch, obj, vict, TO_CHAR);
act("$n gives you $p.", FALSE, ch, obj, vict, TO_VICT);
act("$n gives $p to $N.", TRUE, ch, obj, vict, TO_NOTVICT);
}
/* utility function for give */
struct char_data *give_find_vict(struct char_data *ch, char *arg1)
{
struct char_data *vict;
char arg2[MAX_INPUT_LENGTH];
strcpy(buf, arg1);
argument_interpreter(buf, arg1, arg2);
if (!*arg1) {
send_to_char("Give what to who?\n\r", ch);
return 0;
} else if (!*arg2) {
send_to_char("To who?\n\r", ch);
return 0;
} else if (!(vict = get_char_room_vis(ch, arg2))) {
send_to_char("No-one by that name here.\n\r", ch);
return 0;
} else if (vict == ch) {
send_to_char("What's the point of that?\n\r", ch);
return 0;
} else
return vict;
}
void perform_give_gold(struct char_data *ch, struct char_data *vict,
int amount)
{
if (amount <= 0) {
send_to_char("Heh heh heh ... we are jolly funny today, eh?\n\r", ch);
return;
}
if ((GET_GOLD(ch) < amount) && (IS_NPC(ch) || (GET_LEVEL(ch) < LEVEL_GOD))) {
send_to_char("You haven't got that many coins!\n\r", ch);
return;
}
send_to_char("Ok.\n\r", ch);
sprintf(buf, "%s gives you %d gold coins.\n\r", PERS(ch, vict), amount);
send_to_char(buf, vict);
act("$n gives some gold to $N.", TRUE, ch, 0, vict, TO_NOTVICT);
if (IS_NPC(ch) || (GET_LEVEL(ch) < LEVEL_GOD))
GET_GOLD(ch) -= amount;
GET_GOLD(vict) += amount;
}
ACMD(do_give)
{
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int amount, dotmode;
struct char_data *vict;
struct obj_data *obj, *next_obj;
half_chop(argument, arg1, arg2);
if (!*arg1)
send_to_char("Give what to who?\n\r", ch);
else if (is_number(arg1)) {
amount = atoi(arg1);
if (!(vict = give_find_vict(ch, arg2)))
return;
if (!str_cmp("coins", arg2) || !str_cmp("coin", arg2))
perform_give_gold(ch, vict, amount);
else {
/* code to give multiple items. anyone want to write it? -je */
send_to_char("Sorry, you can't do that (yet)...\n\r", ch);
return;
}
} else {
if (!(vict = give_find_vict(ch, argument)))
return;
dotmode = find_all_dots(argument);
if (dotmode == FIND_ALL) {
if (!ch->carrying)
send_to_char("You don't seem to be holding anything.\n\r", ch);
else for (obj = ch->carrying; obj; obj = next_obj) {
next_obj = obj->next_content;
perform_give(ch, vict, obj);
}
} else if (dotmode == FIND_ALLDOT) {
if (!*argument) {
send_to_char("All of what?\n\r", ch);
return;
}
if (!(obj = get_obj_in_list_vis(ch, argument, ch->carrying))) {
sprintf(buf, "You don't seem to have any %ss.\n\r", argument);
send_to_char(buf, ch);
} else while (obj) {
next_obj = get_obj_in_list_vis(ch, argument, obj->next_content);
perform_give(ch, vict, obj);
obj = next_obj;
}
} else {
if (!(obj = get_obj_in_list_vis(ch, argument, ch->carrying))) {
sprintf(buf, "You don't seem to have %s %s.\n\r", AN(argument), argument);
send_to_char(buf, ch);
} else
perform_give(ch, vict, obj);
}
}
}