/* Crimson2 Mud Server
* All source written/copyright Ryan Haksi 1995 *
* This source code is proprietary. Use in whole or in part without
* explicity permission by the author is strictly prohibited
*
* Current email address(es): cryogen@infoserve.net
* Phone number: (604) 591-5295
*
* C4 Script Language written/copyright Cam Lesiuk 1995
* Email: clesiuk@engr.uvic.ca
*/
/* Inventory related commands */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include "crimson2.h"
#include "macro.h"
#include "queue.h"
#include "log.h"
#include "str.h"
#include "ini.h"
#include "extra.h"
#include "property.h"
#include "file.h"
#include "thing.h"
#include "index.h"
#include "area.h"
#include "reset.h"
#include "code.h"
#include "exit.h"
#include "world.h"
#include "edit.h"
#include "history.h"
#include "socket.h"
#include "send.h"
#include "base.h"
#include "affect.h"
#include "effect.h"
#include "object.h"
#include "board.h"
#include "char.h"
#include "fight.h"
#include "player.h"
#include "skill.h"
#include "parse.h"
#include "cmd_move.h"
#include "cmd_inv.h"
/* Each type of object can be worn in up to 3 different locations
alter the table to taste */
struct WearListType wearList[] = {
{ "NOWEAR", 0, { 0,0,0 } },
{ "HEAD", 0, { EQU_HEAD,
0,
0 } },
{ "NECK", 0, { EQU_NECK_1,
EQU_NECK_2,
0 } },
{ "LARGE-NECK", 0, { EQU_NECK_1|EQU_NECK_2,
0,
0 } },
{ "SHIRT", 0, { EQU_TORSO,
0,
0 } },
{ "UPPER-BODY", 0, { EQU_TORSO|EQU_ARM_R|EQU_ARM_L,
0,
0 } },
{ "ARM", 0, { EQU_ARM_R,
EQU_ARM_L,
0 } },
{ "BOTH-ARMS", 0, { EQU_ARM_R|EQU_ARM_L,
0,
0 } },
{ "WRIST", 0, { EQU_WRIST_R,
EQU_WRIST_L,
0 } },
{ "BOTH-WRISTS", 0, { EQU_WRIST_R|EQU_WRIST_L,
0,
0 } },
{ "HELD", 0, { EQU_HELD_R,
EQU_HELD_L,
EQU_TAILGRIP } },
{ "TWO-HANDED", 0, { EQU_HELD_R|EQU_HELD_L,
0,
0 } },
{ "FINGER", 0, { EQU_FINGER_R,
EQU_FINGER_L,
0 } },
{ "WAIST", 0, { EQU_WAIST,
0,
0 } },
{ "LEGS", 0, { EQU_LEGS,
0,
0 } },
{ "FEET", 0, { EQU_FEET,
0,
0 } },
{ "OVERBODY", 0, { EQU_BODY,
0,
0 } },
{ "EITHER-HAND", 0, { EQU_HAND_R,
EQU_HAND_L,
0 } },
{ "BOTH-HANDS", 0, { EQU_HAND_R|EQU_HAND_L,
0,
0 } },
{ "R-HAND", 0, { EQU_HAND_R,
0,
0 } },
{ "L-HAND", 0, { EQU_HAND_L,
0,
0 } },
{ "MECH-ARM", 0, { EQU_ARM_R|EQU_HELD_R,
EQU_ARM_L|EQU_HELD_L,
0 } },
{ "TAIL", 0, { EQU_TAIL,
0,
0 } },
{ "",0,{ 0,0,0 } }
};
/* internal equipment position flags */
BYTE *equipList[] = {
"HEAD",
"NECK",
"NECK",
"TORSO",
"OVER-BODY",
"RIGHT-ARM",
"LEFT-ARM",
"RIGHT-WRIST",
"LEFT-WRIST",
"RIGHT-HAND",
"LEFT-HAND",
"HELD-IN-RIGHT-HAND",
"HELD-IN-LEFT-HAND",
"FINGER-ON-RIGHT-HAND",
"FINGER-ON-LEFT-HAND",
"WAIST",
"LEGS",
"FEET",
"TAIL",
"GRIPPED-IN-TAIL",
""
};
CMDPROC(CmdGet) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
BYTE buf[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found;
THING *search;
FLAG flag;
THING *world;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
if (*dstKey) { /* search a target */
search = CharThingFind(thing, dstKey, -1, thing, TF_OBJ, &dstOffset);
if (!search)
search = CharThingFind(thing, dstKey, -1, Base(thing)->bInside, TF_OBJ, &dstOffset);
if (!search) {
SendThing("^bThere doesnt appear to be anything like that around to look in\n", thing);
return;
}
} else /* search the room */
search = Base(thing)->bInside;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything to get\n", thing);
while (found && srcNum!=0) {
if (found->tType==TTYPE_OBJ && (Base(found)->bWeight<0)) {
/* cant grab an item with negative weight or NOTAKE item */
SendAction("^bYou ^ccant^b take ^g$N\n",
thing, found, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST);
} else if (!CharCanCarry(thing, found)) {
/* check if too heavy */
SendAction("^b$N is too heavy for you to lift\n",
thing, found, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST);
} else {
/* Check whether we are looting a corpse */
if (*dstKey
&& search->tType==TTYPE_OBJ
&& Obj(search)->oTemplate->oType==OTYPE_CONTAINER)
{
flag=OBJECTGETFIELD(search, OF_CONTAINER_CFLAG);
if ( BIT(flag, OCF_CLOSED) ) {
SendAction("^bYou try to take something from ^g$N ^b, then realize its closed\n",
thing, search, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n tries to take something from ^g$N ^b, then realizes that its closed\n",
thing, search, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
return;
} else if ( BIT(flag, OCF_PLAYERCORPSE) ) {
/* check whether we are looting our OWN corpse */
sprintf(buf, FIGHT_CORPSE_KEY, Base(thing)->bKey->sText);
if (STRICMP(Base(search)->bKey->sText, buf)) {
if (BIT(flag, OCF_PLAYERLOOTED)) {
SendAction("^wYou try to loot ^g$N ^wbut someone beat you to it\n",
thing, search, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n tries to loot ^g$N ^wbut someone beat $m to it\n",
thing, search, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
return;
} else {
BITSET(flag, OCF_PLAYERLOOTED);
OBJECTSETFIELD(search, OF_CONTAINER_CFLAG, flag);
srcNum = 0; /* only one object */
}
}
}
}
/* guess we can take it */
SendAction("^bYou get ^g$N",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n gets ^g$N",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
/* complete the action */
if (*dstKey) {
SendAction(" ^bfrom $S ^g$N", thing, search, SEND_SRC|SEND_ROOM|SEND_VISIBLE);
}
SendAction("\n", thing, search, SEND_SRC|SEND_ROOM|SEND_VISIBLE);
if (found->tType==TTYPE_OBJ
&& Obj(found)->oTemplate->oValue<5
&& Obj(found)->oTemplate->oValue>=0
&& thing->tType==TTYPE_PLR
&& BIT(Plr(thing)->pAuto, PA_AUTOJUNK)) {
/* autojunk it its worthless */
SendAction("^CYou autojunk ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^C$n autojunks ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
ThingFree(found);
} else {
/* move the object into the chars inventory */
if (found->tType==TTYPE_OBJ&&Obj(found)->oTemplate->oType==OTYPE_MONEY) {
/* guard against no gain zones etc here */
world = Base(thing)->bInside;
if (world->tType==TTYPE_WLD
&& BIT(areaList[Wld(world)->wArea].aResetFlag, RF_NOMONEY)) {
sprintf(buf, "^yYou ^rWOULD ^yhave gained %ld credits! (This zone isnt open yet)\n", OBJECTGETFIELD(found, OF_MONEY_AMOUNT));
SendThing(buf, thing);
} else {
sprintf(buf, "^yYou get %ld credits!\n", OBJECTGETFIELD(found, OF_MONEY_AMOUNT));
SendThing(buf, thing);
Character(thing)->cMoney += OBJECTGETFIELD(found, OF_MONEY_AMOUNT);
}
THINGFREE(found);
} else {
ThingTo(found, thing);
}
}
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdDrop) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found;
THING *search;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (InvUnEquip(thing, found, IUE_BLOCKABLE)) {
SendAction("^bYou drop ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n drops ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
ThingTo(found, Base(thing)->bInside);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdJunk) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
THING *search;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (InvUnEquip(thing, found, IUE_BLOCKABLE)) {
SendAction("^bYou junk ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n junks ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
ThingFree(found);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdPut) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found = NULL;
THING *search = NULL;
THING *dest = NULL;
THING *ammo = NULL;
LWORD ammoType;
LWORD ammoUse;
LWORD ammoLeft;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
if (*dstKey) { /* search a target */
dest = CharThingFind(thing, dstKey, -1, thing, TF_OBJ, &dstOffset);
if (!dest) /* search the room */
dest = CharThingFind(thing, dstKey, -1, Base(thing)->bInside, TF_OBJ, &dstOffset);
} else
dest = NULL;
if (!dest)
SendThing("^bThere doesnt appear to be anything like that to put things into\n", thing);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found) { /* also search ourself if no 2nd object specified */
search = Base(thing)->bInside;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ, &srcOffset);
}
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (dest) {
ammo = ObjectGetAmmo(dest, &ammoType, &ammoUse, &ammoLeft);
if ( (Obj(dest)->oTemplate->oType == OTYPE_CONTAINER)
||(Obj(found)->oTemplate->oType == OTYPE_AMMO
&& ammoType
&& OBJECTGETFIELD(found, OF_AMMO_AMMOTYPE) == ammoType)
) {
if ( (Obj(dest)->oTemplate->oType == OTYPE_CONTAINER
&& Base(dest)->bConWeight + Base(found)->bWeight > OBJECTGETFIELD(dest, OF_CONTAINER_MAX))
||(ammoType
&& ammo)
) {
SendThing("^bYou cant fit that in there!\n", thing);
return;
} else if (Obj(dest)->oTemplate->oType == OTYPE_CONTAINER
&& BIT(OBJECTGETFIELD(dest, OF_CONTAINER_CFLAG), OCF_CLOSED)
) {
SendThing("^bBut its closed!\n", thing);
return;
} else if (dest == found) {
SendThing("^bYou cant put something inside itself!\n", thing);
return;
} else {
SendAction("^bYou put ^g$N",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n puts ^g$N",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
SendAction(" ^binto ^g$N\n",
thing, dest, SEND_SRC|SEND_ROOM|SEND_VISIBLE);
ThingTo(found, dest);
}
} else {
SendThing("^bYou cant put that in there!\n", thing);
return;
}
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (!found) { /* also search room if no 2nd object specified */
search = Base(thing)->bInside;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ|TF_CONTINUE, &srcOffset);
}
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdGive) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE buf[256];
BYTE srcKey[256];
BYTE dstKey[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found;
THING *search;
THING *dest;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
/* search the room for a target */
if (*dstKey) {
dest = CharThingFind(thing, dstKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &dstOffset);
} else
dest = NULL;
if (!dest) {
SendThing("^bThere doesnt appear to be anyone like that to give things to\n", thing);
return;
}
/* search ourself for an object */
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
/* intercept here to give credits */
if ( (!found && StrAbbrev("credits", srcKey))
|| (StrExact("credits", srcKey)) )
{
if (srcNum < 0) {
SendThing("^wAnd how does that work again!?!\n", thing);
return;
} else if (srcNum > Character(thing)->cMoney) {
SendThing("^wYou dont have that much money!\n", thing);
return;
} else {
/* transfer the money */
Character(thing)->cMoney -= srcNum;
Character(dest)->cMoney += srcNum;
/* send the messages */
sprintf(buf, "^CYou give $N %ld credits\n", srcNum);
SendAction(buf, thing, dest, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
sprintf(buf, "^b$n gives you %ld credits\n", srcNum);
SendAction(buf, thing, dest, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST);
sprintf(buf, "^C$n gives $N some money\n");
SendAction(buf, thing, dest, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
return;
}
}
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around to give\n", thing);
return;
}
while (found && srcNum!=0) {
if (Base(found)->bWeight + Base(dest)->bConWeight > CharGetCarryMax(dest)) {
SendAction("^CYou try to give ^g$N",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^C$n tries to give ^g$N",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
SendAction(" ^Cto ^g$N^C, but its too heavy!\n",
thing, dest, SEND_SRC|SEND_ROOM|SEND_VISIBLE);
SendAction(" ^bto ^gyou^C, but its too heavy!\n",
thing, dest, SEND_DST|SEND_VISIBLE);
} else {
SendAction("^bYou give ^g$N",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n gives ^g$N",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
SendAction(" ^bto ^g$N\n",
thing, dest, SEND_SRC|SEND_ROOM|SEND_VISIBLE);
SendAction(" ^bto ^gyou\n",
thing, dest, SEND_DST|SEND_VISIBLE);
ThingTo(found, dest);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
/* Add direct applies of an equipped item */
void InvApply(THING *thing, THING *equip) {
LWORD apply;
LWORD aType;
LWORD aValue;
switch (Obj(equip)->oTemplate->oType) {
case OTYPE_ARMOR:
Effect(AFFECT_ARMOR, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_ARMOR));
Effect(AFFECT_RES_PUNCTURE, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RPUNCTURE));
Effect(AFFECT_RES_SLASH, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RSLASH));
Effect(AFFECT_RES_CONCUSSIVE, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RCONCUSSIVE));
Effect(AFFECT_RES_HEAT, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RHEAT));
Effect(AFFECT_RES_EMR, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_REMR));
Effect(AFFECT_RES_LASER, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RLASER));
Effect(AFFECT_RES_PSYCHIC, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RPSYCHIC));
Effect(AFFECT_RES_ACID, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RACID));
Effect(AFFECT_RES_POISON, TAR_AFFECT, thing, NULL, OBJECTGETFIELD(equip, OF_ARMOR_RPOISON));
break;
}
/* apply direct effects */
for (apply=0; apply < OBJECT_MAX_APPLY; apply++) {
aType = Obj(equip)->oApply[apply].aType;
if (applyList[aType].aTarget==TAR_AFFECT) {
aValue = Obj(equip)->oApply[apply].aValue;
Effect(applyList[aType].aEffect, applyList[aType].aTarget, thing, NULL, aValue);
}
}
}
/* return FALSE if we cant equip this */
BYTE InvEquip(THING *thing, THING *equip, BYTE *message) {
LWORD i;
LWORD wearType;
LWORD apply;
LWORD aType;
LWORD aValue;
THING *ammo;
LWORD ammoType;
LWORD ammoUse;
LWORD ammoLeft;
if (message) message[0]='\0';
/* MinStr etc */
if (thing->tType == TTYPE_PLR) {
if (Plr(thing)->pStr < PropertyGetLWord(thing, "%MINSTR", 0)) {
if (message) sprintf(message, "You are not strong enough\n");
return FALSE;
}
if (Plr(thing)->pDex < PropertyGetLWord(thing, "%MINDEX", 0)) {
if (message) sprintf(message, "You are not dexterous enough\n");
return FALSE;
}
if (Plr(thing)->pCon < PropertyGetLWord(thing, "%MINCON", 0)) {
if (message) sprintf(message, "You are not tough enough\n");
return FALSE;
}
if (Plr(thing)->pWis < PropertyGetLWord(thing, "%MINWIS", 0)) {
if (message) sprintf(message, "You are not wise enough\n");
return FALSE;
}
if (Plr(thing)->pInt < PropertyGetLWord(thing, "%MININT", 0)) {
if (message) sprintf(message, "You are not smart enough\n");
return FALSE;
}
}
if (Character(thing)->cLevel < PropertyGetLWord(thing, "%MINLEVEL", 0)) {
if (message) sprintf(message, "You are not high enough in level\n");
return FALSE;
}
/* Aura check */
if (Character(thing)->cAura>400) {
if (BIT(Obj(equip)->oAct, OA_ANTI_GOOD)) {
if (message) sprintf(message, "You are too good\n");
return FALSE;
}
} else if (Character(thing)->cAura<-400) {
if (BIT(Obj(equip)->oAct, OA_ANTI_EVIL)) {
if (message) sprintf(message, "You are too evil\n");
return FALSE;
}
} else if (BIT(Obj(equip)->oAct, OA_ANTI_NEUTRAL)) {
if (message) sprintf(message, "You are too neutral\n");
return FALSE;
}
/* ensure they have ammo for it */
if (thing->tType==TTYPE_PLR && Obj(equip)->oTemplate->oType!=OTYPE_WEAPON) {
ammo = ObjectGetAmmo(equip, &ammoType, &ammoUse, &ammoLeft);
if (!ammo && ammoType) {
if (message) sprintf(message, "It is out of ammo\n");
return FALSE;
}
}
wearType = Obj(equip)->oTemplate->oWear;
/* for loop searches for an available location to equip the item in */
for (i=0; i<MAX_EQUIP; i++) {
if (!wearList[wearType].wEquipList[i]) continue;
if ( ( (thing->tType == TTYPE_PLR)
&&(!BITANY(Character(thing)->cEquip, wearList[wearType].wEquipList[i]))
&&( BIT(raceList[Plr(thing)->pRace].rLocation, wearList[wearType].wEquipList[i]))
&&(!wearList[wearType].wEquipNot || !BITANY(raceList[Plr(thing)->pRace].rLocation, wearList[wearType].wEquipNot))
)
||( (thing->tType == TTYPE_MOB)
&&(!BITANY(Character(thing)->cEquip, wearList[wearType].wEquipList[i]))
)
)
{
BITSET(Obj(equip)->oEquip, wearList[wearType].wEquipList[i]);
BITSET(Character(thing)->cEquip, wearList[wearType].wEquipList[i]);
switch (Obj(equip)->oTemplate->oType) {
case OTYPE_WEAPON:
Character(thing)->cWeapon = equip;
break;
case OTYPE_LIGHT:
if (Base(thing)->bInside->tType==TTYPE_WLD)
Wld(Base(thing)->bInside)->wLight += OBJECTGETFIELD(equip, OF_LIGHT_INTENSITY);
break;
}
InvApply(thing, equip);
/* add non-direct applies */
for (apply=0; apply < OBJECT_MAX_APPLY; apply++) {
aType = Obj(equip)->oApply[apply].aType;
if (applyList[aType].aTarget!=TAR_AFFECT) {
aValue = Obj(equip)->oApply[apply].aValue;
Effect(applyList[aType].aEffect, applyList[aType].aTarget, thing, NULL, aValue);
}
}
return TRUE;
}
}
if (message) sprintf(message, "You have no place available to use that\n");
return FALSE;
}
/* Temporarily remove applies of an equipped item, must reapply in same routine */
void InvUnapply(THING *thing, THING *equip) {
LWORD apply;
LWORD aType;
LWORD aValue;
switch (Obj(equip)->oTemplate->oType) {
case OTYPE_ARMOR:
EffectFree(AFFECT_ARMOR, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_ARMOR));
EffectFree(AFFECT_RES_PUNCTURE, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RPUNCTURE));
EffectFree(AFFECT_RES_SLASH, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RSLASH));
EffectFree(AFFECT_RES_CONCUSSIVE, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RCONCUSSIVE));
EffectFree(AFFECT_RES_HEAT, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RHEAT));
EffectFree(AFFECT_RES_EMR, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_REMR));
EffectFree(AFFECT_RES_LASER, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RLASER));
EffectFree(AFFECT_RES_PSYCHIC, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RPSYCHIC));
EffectFree(AFFECT_RES_ACID, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RACID));
EffectFree(AFFECT_RES_POISON, TAR_AFFECT, thing, OBJECTGETFIELD(equip, OF_ARMOR_RPOISON));
break;
}
/* remove direct effects */
for (apply=0; apply < OBJECT_MAX_APPLY; apply++) {
aType = Obj(equip)->oApply[apply].aType;
if (applyList[aType].aTarget==TAR_AFFECT) {
aValue = Obj(equip)->oApply[apply].aValue;
EffectFree(applyList[aType].aEffect, applyList[aType].aTarget, thing, aValue);
}
}
}
/* return FALSE if we cant unequip this */
BYTE InvUnEquip(THING *thing, THING *equip, BYTE blockable) {
LWORD apply;
LWORD aType;
LWORD aValue;
/* check params for validity */
if (!thing || !equip) return TRUE;
if (thing->tType < TTYPE_CHARACTER) return TRUE;
/* Check to see if its allready unequipped */
if (equip->tType!=TTYPE_OBJ || Obj(equip)->oEquip==0)
return TRUE;
/* If we can, unequip it */
if (blockable) {
if (BIT(Obj(equip)->oAct, OA_NODROP))
return FALSE;
}
BITCLR(Character(thing)->cEquip, Obj(equip)->oEquip);
Obj(equip)->oEquip = 0;
switch (Obj(equip)->oTemplate->oType) {
case OTYPE_WEAPON:
if (Character(thing)->cWeapon == equip)
Character(thing)->cWeapon = NULL;
break;
case OTYPE_LIGHT:
if (Base(thing)->bInside && Base(thing)->bInside->tType==TTYPE_WLD)
Wld(Base(thing)->bInside)->wLight -= OBJECTGETFIELD(equip, OF_LIGHT_INTENSITY);
break;
}
InvUnapply(thing, equip);
/* remove non-direct apply's */
for (apply=0; apply < OBJECT_MAX_APPLY; apply++) {
aType = Obj(equip)->oApply[apply].aType;
if (applyList[aType].aTarget!=TAR_AFFECT) {
aValue = Obj(equip)->oApply[apply].aValue;
EffectFree(applyList[aType].aEffect, applyList[aType].aTarget, thing, aValue);
}
}
return TRUE;
}
void InvEquipShow(THING *thing) {
BYTE buf[256];
LWORD shotLeft;
THING *ammo;
LWORD ammoType;
LWORD ammoUse;
LWORD ammoLeft;
LWORD fireRate;
SendThing("^pYou are currently Equipped with:\n", thing);
SendThing("^P-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n", thing);
CharShowEquip(thing, thing); /* show them their own equip list */
/* Show Weapon */
if (Character(thing)->cWeapon) {
SendThing("\n^GYour Currently Selected Weapon is:\n^g", thing);
SendThing(Character(thing)->cWeapon->tSDesc->sText, thing);
ammo = ObjectGetAmmo(Character(thing)->cWeapon, &ammoType, &ammoUse, &ammoLeft);
if (ammoUse>0) {
if (!ammo) {
SendThing(" ^r<UNLOADED>", thing);
} else if (ammoLeft<0) {
SendThing(" ^r<UNLIMITED AMMO>", thing);
} else {
fireRate = OBJECTGETFIELD(Character(thing)->cWeapon, OF_WEAPON_FIRERATE);
shotLeft = ammoLeft/ammoUse;
if (!shotLeft) {
SendThing(" ^w<OUT OF AMMO>", thing);
} else if ( fireRate*3 > shotLeft) {
sprintf(buf, " ^r<Only %ld shots left!>", shotLeft);
SendThing(buf, thing);
} else {
sprintf(buf, " ^y<%ld shots left>", shotLeft);
SendThing(buf, thing);
}
}
} else
SendThing(" ^r<NO AMMO NEEDED>", thing);
SendThing("\n", thing);
}
}
/* Eat primitive, called by CmdEat as well as PlayerTick */
void InvEat(THING *thing, THING *found) {
LWORD poison;
SendAction("^bYou eat ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n eats ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
if (thing->tType == TTYPE_PLR) {
Plr(thing)->pHunger -= OBJECTGETFIELD(found, OF_FOOD_HOWFILLING);
/* ADD: Check OF_FOOD_POISON here too */
poison = OBJECTGETFIELD(found, OF_FOOD_POISON);
if (poison > 0)
Effect(EFFECT_POISON, TAR_SELF_DEF, thing, "", poison);
/* check min hunger against race */
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxThirst), Plr(thing)->pThirst, raceList[Plr(thing)->pRace].rMaxThirst);
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxHunger), Plr(thing)->pHunger, raceList[Plr(thing)->pRace].rMaxHunger);
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxIntox) , Plr(thing)->pIntox, raceList[Plr(thing)->pRace].rMaxIntox );
}
THINGFREE(found);
}
/* Eat primitive, called by CmdEat as well as PlayerTick */
void InvDrink(THING *thing, THING *found) {
LWORD liquid;
LWORD liquidLeft;
LWORD poison;
if (Base(found)->bInside != thing) {
SendAction("^bYou take a drink from $A ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n takes a drink from $A ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
} else {
SendAction("^bYou take a drink from your ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n takes a drink from $s ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}
if (thing->tType == TTYPE_PLR) {
liquid = OBJECTGETFIELD(found, OF_DRINKCON_LIQUID);
TYPECHECK(liquid, oLiquidList);
/* thirst */
if (Plr(thing)->pThirst>=-1*raceList[Plr(thing)->pRace].rMaxThirst) {
Plr(thing)->pThirst -= oLiquidList[liquid].oLThirst;
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxThirst), Plr(thing)->pThirst, raceList[Plr(thing)->pRace].rMaxThirst);
}
/* Hunger */
if (Plr(thing)->pHunger>=-1*raceList[Plr(thing)->pRace].rMaxHunger) {
Plr(thing)->pHunger += oLiquidList[liquid].oLHunger;
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxHunger), Plr(thing)->pHunger, raceList[Plr(thing)->pRace].rMaxHunger);
}
/* Intox */
if (Plr(thing)->pIntox>=-1*raceList[Plr(thing)->pRace].rMaxIntox) {
Plr(thing)->pIntox += oLiquidList[liquid].oLIntox;
BOUNDSET((-1*raceList[Plr(thing)->pRace].rMaxIntox) , Plr(thing)->pIntox, raceList[Plr(thing)->pRace].rMaxIntox );
}
if (oLiquidList[liquid].oLPoison > 0)
Effect(EFFECT_POISON, TAR_SELF_DEF, thing, "", oLiquidList[liquid].oLPoison);
}
/* ADD: Check OF_DRINKCON_POISON here too */
poison = OBJECTGETFIELD(found, OF_DRINKCON_POISON);
if (poison > 0)
Effect(EFFECT_POISON, TAR_SELF_DEF, thing, "", poison);
liquidLeft = OBJECTGETFIELD(found, OF_DRINKCON_CONTAIN);
if (liquidLeft>0) {
liquidLeft--;
MINSET(liquidLeft, 0);
}
OBJECTSETFIELD(found, OF_DRINKCON_CONTAIN, liquidLeft);
}
CMDPROC(CmdEquip) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
BYTE message[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
if (!*cmd) { /* give the player the list of things they have equipped */
InvEquipShow(thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJINV, &srcOffset);
if (!found) {
SendThing("^bEquip what?!?\n", thing);
return;
}
while(found && srcNum!=0) {
if (Obj(found)->oEquip==0) {
if (InvEquip(thing, found, message)) {
SendAction("^bYou equip yourself with ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n equips $mself with ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
} else {
/* was unable to equip the item */
if (STRICMP(srcKey, "all")) {
SendThing("^bYou dont seem to be able to equip ^g", thing);
SendThing(found->tSDesc->sText, thing);
SendThing("\n", thing);
SendThing(message, thing);
}
}
}
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdUnEquip) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
AFFECT *affect;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
if (!*cmd) { /* give the player the list of things they have equipped */
InvEquipShow(thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJEQUIP, &srcOffset);
if (!found) {
SendThing("^bUnEquip what?!?\n", thing);
return;
}
while(found && srcNum!=0) {
if (Obj(found)->oEquip!=0) {
/* Expire the psi-power object */
if (Obj(found)->oTemplate == phantomPocketTemplate) {
affect = AffectFind(thing, EFFECT_PHANTOMPOCKET);
if (affect) AffectRemove(thing, affect);
/* Expire the psi-power object */
} else if (Obj(found)->oTemplate == fireBladeTemplate) {
affect = AffectFind(thing, EFFECT_FIREBLADE);
if (affect) AffectRemove(thing, affect);
/* Expire the psi-power object */
} else if (Obj(found)->oTemplate == fireShieldTemplate) {
affect = AffectFind(thing, EFFECT_FIRESHIELD);
if (affect) AffectRemove(thing, affect);
/* Expire the psi-power object */
} else if (Obj(found)->oTemplate == fireArmorTemplate) {
affect = AffectFind(thing, EFFECT_FIREARMOR);
if (affect) AffectRemove(thing, affect);
/* Try to unequip it */
} else if (InvUnEquip(thing, found, IUE_BLOCKABLE)) {
SendAction("^bYou unequip ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n unequips ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
/* was unable to unequip the item */
} else {
SendThing("^bYou dont seem to be able to unequip ^g", thing);
SendThing(found->tSDesc->sText, thing);
SendThing("\n", thing);
}
}
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJEQUIP|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdInventory) { /* void CmdProc(THING *thing, BYTE* cmd) */
THING *show;
BYTE buf[256];
SOCK *sock;
BYTE expert = FALSE;
sock = BaseControlFind(thing);
if (sock && BIT(Plr(sock->sHomeThing)->pAuto, PA_EXPERT)) expert = TRUE;
if (Base(thing)->bConWeight <= CharGetCarryMax(thing)/4)
sprintf(buf,
"^pYou are currently carrying: ^w%hd/%ld pounds ^y(Move cost = Normal)\n",
Base(thing)->bConWeight,
CharGetCarryMax(thing));
else if (Base(thing)->bConWeight <= CharGetCarryMax(thing)/2)
sprintf(buf,
"^pYou are currently carrying: ^w%hd/%ld pounds ^y(Move cost = 1.5X)\n",
Base(thing)->bConWeight,
CharGetCarryMax(thing));
else if (Base(thing)->bConWeight <= 75*CharGetCarryMax(thing)/100)
sprintf(buf,
"^pYou are currently carrying: ^w%hd/%ld pounds ^y(Move cost = 2X)\n",
Base(thing)->bConWeight,
CharGetCarryMax(thing));
else
sprintf(buf,
"^pYou are currently carrying: ^w%hd/%ld pounds ^y(Move cost = 2.5X)\n",
Base(thing)->bConWeight,
CharGetCarryMax(thing));
SendThing(buf, thing);
SendThing("^P-=-=-=-=-=-=-=-=-=-=-=-=-=-\n", thing);
show=thing->tContain;
while (show) {
if (show->tType!=TTYPE_OBJ || Obj(show)->oEquip==0) {
show = ThingShow(show, thing);
} else
show = show->tNext;
}
/* Hint for total newbies */
if (Character(thing)->cEquip && Character(thing)->cLevel<=5 && !expert)
SendHint("^;HINT: To see what you are equipped with, type ^<EQUIP\n", thing);
}
CMDPROC(CmdEat) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
THING *search;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (InvUnEquip(thing, found, IUE_BLOCKABLE)) {
if (Obj(found)->oTemplate->oType == OTYPE_FOOD) {
InvEat(thing, found);
} else {
SendAction("^bYou try to eat the ^g$N ^bthen realize it isnt food\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n tries to eat $A ^g$N ^bthen realizes it isnt food\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}
} else {
SendAction("^bYou dont seem to be able to unequip ^g$N ^blong enough to eat it!\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n doesnt seem to be able to unequip ^g$N ^blong enough to eat it!\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdDrink) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
THING *search;
LWORD liquidLeft;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (Obj(found)->oTemplate->oType == OTYPE_DRINKCON) {
liquidLeft = OBJECTGETFIELD(found, OF_DRINKCON_CONTAIN);
if (liquidLeft!=0) {
InvDrink(thing, found);
} else {
SendAction("^bYou try to drink from ^g$N ^bthen realize its empty\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n tries to drink from ^g$N ^bthen realizes its empty\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}
} else {
SendAction("^bYou try to drink from ^g$N ^bthen realizes it isnt possible\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n tries to eat $A ^g$N ^bthen realizes it isnt possible\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdFill) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
THING *found = NULL;
THING *search = NULL;
THING *dest = NULL;
LWORD maxFound;
LWORD containFound;
LWORD liquidFound;
LWORD poisonFound;
LWORD containDest;
LWORD liquidDest;
LWORD poisonDest;
LWORD transfer;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
if (*dstKey) { /* search a target */
dest = CharThingFind(thing, dstKey, -1, thing, TF_OBJINV, &dstOffset);
if (!dest) /* search the room */
dest = CharThingFind(thing, dstKey, -1, Base(thing)->bInside, TF_OBJ, &dstOffset);
} else
dest = NULL;
if (!dest) {
SendThing("^bTry something along the lines of ^wfill canteen fountain\n", thing);
return;
}
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if ( (Obj(found)->oTemplate->oType == OTYPE_DRINKCON)
&&(Obj(dest )->oTemplate->oType == OTYPE_DRINKCON)
) {
/* Read data from found */
maxFound = OBJECTGETFIELD(found, OF_DRINKCON_MAX);
containFound = OBJECTGETFIELD(found, OF_DRINKCON_CONTAIN);
liquidFound = OBJECTGETFIELD(found, OF_DRINKCON_LIQUID);
poisonFound = OBJECTGETFIELD(found, OF_DRINKCON_POISON);
/* read data from dest */
containDest = OBJECTGETFIELD(dest, OF_DRINKCON_CONTAIN);
liquidDest = OBJECTGETFIELD(dest, OF_DRINKCON_LIQUID);
poisonDest = OBJECTGETFIELD(dest, OF_DRINKCON_POISON);
if (containFound!=0 && liquidFound != liquidDest) {
/* source allready has a different liquid in it */
SendAction("^bYou start to fill your ^g$N^b, then realize that you allready have something in it\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n starts to fill $s ^g$N^b, then realizes that $h allready has something in it\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
} else if (containFound<0 || containFound>=maxFound) {
/* trying to fill to an infinite source or full drinkcon */
SendAction("^bYou start to fill your ^g$N^b, then realize its allready full\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n starts to fill $s ^g$N^b, then realizes that its allready full\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
} else if (containDest == 0) {
/* trying to fill from a empty drinkcon */
SendAction("^bYou start to fill your ^g$N",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n starts to fill $s ^g$N",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b, but the ^g$N^b is empty\n",
thing, dest, SEND_SRC|SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE);
} else if (dest==found) {
/* trying to fill a drinkcon from itself */
SendAction("^bYou fill your ^g$N ^bfrom itself (real productive).",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction(
"^b$n fills ^g$N ^bfrom itself (bright as a bubble, that one).",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
} else {
/* perform the fill */
transfer = maxFound - containFound;
if (containDest>=0) {
MAXSET(transfer, containDest);
containDest -= transfer;
OBJECTSETFIELD(dest, OF_DRINKCON_CONTAIN, containDest);
}
containFound+=transfer;
OBJECTSETFIELD(found, OF_DRINKCON_CONTAIN, containFound);
/* Poison accordingly */
if (poisonDest > poisonFound) {
poisonFound = poisonDest;
OBJECTSETFIELD(found, OF_DRINKCON_POISON, poisonFound);
}
SendAction("^bYou fill your ^g$N",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n fills $s ^g$N",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction(" ^bfrom the ^g$N\n",
thing, dest, SEND_SRC|SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE);
}
} else {
SendAction("^bYou cant fill your $N",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^bfrom the $N!\n",
thing, dest, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdEmpty) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
BYTE dstKey[256];
LWORD srcNum;
LWORD srcOffset;
LWORD dstOffset;
LWORD contain;
THING *found;
THING *search;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, dstKey, &dstOffset);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset);
if (!found)
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
while (found && srcNum!=0) {
if (Obj(found)->oTemplate->oType == OTYPE_DRINKCON) {
contain = OBJECTGETFIELD(found, OF_DRINKCON_CONTAIN);
if (contain>0) {
/* full container */
SendAction("^bYou empty your ^g$N ^bon the floor\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n empties $s ^g$N ^bon the floor\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
OBJECTSETFIELD(found, OF_DRINKCON_CONTAIN, 0);
OBJECTSETFIELD(found, OF_DRINKCON_POISON, 0);
} else if (contain==0) {
/* empty container */
SendAction("^bYou hold your ^g$N ^bupside down and shake, but nothing comes out\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n holds $s ^g$N ^bupside down and shakes it, but nothing comes out\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
} else {
/* infinite liquid source */
SendAction("^bYou hold your ^g$N ^bupside down and spray liquid all over the floor\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n holds $s ^g$N ^bupside down and sprays liquid all over the floor\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
}
} else {
SendAction("^bYou empty your ^g$N\n",
thing, found, SEND_SRC |SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n empties $s ^g$N\n",
thing, found, SEND_ROOM|SEND_AUDIBLE|SEND_VISIBLE|SEND_CAPFIRST);
}
while(found->tContain)
ThingTo(found->tContain, Base(found)->bInside);
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}
CMDPROC(CmdRead) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
LWORD i;
LWORD board;
BYTE *origCmd;
origCmd = cmd;
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
SendThing("^rTry Read <Object>\n", thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJ, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found) {
/* SendThing("^bThere doesnt appear to be anything like that around\n", thing); */
CmdLook(thing, origCmd);
return;
}
if (Obj(found)->oTemplate->oType!=OTYPE_BOARD) {
/* SendThing("^bThat sort of thing cant have anything written on it.\n", thing); */
CmdLook(thing, origCmd);
return;
}
board = BoardOf(OBJECTGETFIELD(found, OF_BOARD_BVIRTUAL));
if (board == -1) {
SendThing("^wTell whoever created this thing that the virtual # is invalid\n", thing);
return;
}
/* List of message titles */
if (!*cmd) {
BoardShow(board, thing);
SendHint("^;HINT: Try ^<Read ^;<object> <msg#> to read a message\n", thing);
return;
}
i = -1;
sscanf(cmd, " %ld", &i);
i -= 1;
if (i<0 || i>= boardList[board].bIndex.iNum) {
SendThing("^wThere is no message with that number\n", thing);
return;
}
BoardShowMessage(board, i, thing);
}
CMDPROC(CmdEdit) {
LWORD board;
BYTE strName[256];
BOARDMSG *boardMsg;
LWORD i;
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
if (thing->tType!=TTYPE_PLR) {
SendThing("^rMobs cant edit messages\n", thing);
return;
}
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
SendThing("^rTry Edit <Object> <msg #>\n", thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJ, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return;
}
if (Obj(found)->oTemplate->oType!=OTYPE_BOARD) {
SendThing("^bThat sort of thing can have anything written on it.\n", thing);
return;
}
board = BoardOf(OBJECTGETFIELD(found, OF_BOARD_BVIRTUAL));
if (board == -1) {
SendThing("^wTell whoever created this thing that the virtual # is invalid\n", thing);
return;
}
/* check virtual # */
i = -1;
sscanf(cmd, " %ld", &i);
i -= 1;
if (i<0 || i>= boardList[board].bIndex.iNum) {
SendThing("^wThere is no message with that number\n", thing);
return;
}
boardMsg = BoardMsg(boardList[board].bIndex.iThing[i]);
if ( (Character(thing)->cLevel<LEVEL_CODER)
||(!StrExact(thing->tSDesc->sText, boardMsg->bAuthor->sText)) ) {
SendThing("^rYou can only edit your own messages\n", thing);
return;
}
sprintf(strName, "Board [%s]- Edit", boardList[board].bFileName);
EDITSTR(thing, boardMsg->bText, 2048, strName, EP_ENDLF|EP_IMMNEW);
EDITFLAG(thing, &boardList[board].bFlag, B_UNSAVED);
}
CMDPROC(CmdWrite) {
LWORD board;
BYTE strName[256];
BOARDMSG *boardMsg;
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
SendThing("^rTry Write <Object> <Message Title>\n", thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJ, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return;
}
if (Obj(found)->oTemplate->oType!=OTYPE_BOARD) {
SendThing("^bThat sort of thing can have anything written on it.\n", thing);
return;
}
board = BoardOf(OBJECTGETFIELD(found, OF_BOARD_BVIRTUAL));
if (board == -1) {
SendThing("^wTell whoever created this thing that the virtual # is invalid\n", thing);
return;
}
/* chuck virtual # */
if (!*cmd)
boardMsg = BoardMsgCreate(board, thing, "^Y<No Title>", BOARD_NOTREPLY);
else
boardMsg = BoardMsgCreate(board, thing, cmd, BOARD_NOTREPLY);
if (!boardMsg) {
SendThing("^rNot good, critical error aborting message\n", thing);
return;
}
sprintf(strName, "Board [%s] - Write", boardList[board].bFileName);
EDITSTR(thing, boardMsg->bText, 2048, strName, EP_ENDLF|EP_IMMNEW);
EDITFLAG(thing, &boardList[board].bFlag, B_UNSAVED);
}
CMDPROC(CmdReply) {
LWORD board;
BYTE titleBuf[50];
BYTE strName[256];
BOARDMSG *boardMsg;
LWORD i;
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
SendThing("^rTry Reply <Object> <msg #> [<msg title>]\n", thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJ, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return;
}
if (Obj(found)->oTemplate->oType!=OTYPE_BOARD) {
SendThing("^bThat sort of thing cant have anything written on it.\n", thing);
return;
}
board = BoardOf(OBJECTGETFIELD(found, OF_BOARD_BVIRTUAL));
if (board == -1) {
SendThing("^wTell whoever created this thing that the virtual # is invalid\n", thing);
return;
}
/* check msg # */
i = -1;
sscanf(cmd, " %ld", &i);
i -= 1;
if (i<0 || i>= boardList[board].bIndex.iNum) {
SendThing("^wThere is no message with that number\n", thing);
return;
}
boardMsg = BoardMsg(boardList[board].bIndex.iThing[i]);
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
strcpy(titleBuf, "Re:");
strncpy(titleBuf+3, boardMsg->bTitle->sText, sizeof(titleBuf)-3);
titleBuf[sizeof(titleBuf)-1] = 0;
boardMsg = BoardMsgCreate(board, thing, titleBuf, i);
} else
boardMsg = BoardMsgCreate(board, thing, cmd, i);
if (!boardMsg) {
SendThing("^rNot good, critical error aborting message\n", thing);
return;
}
sprintf(strName, "Board [%s] - Reply", boardList[board].bFileName);
EDITSTR(thing, boardMsg->bText, 2048, strName, EP_ENDLF|EP_IMMNEW);
EDITFLAG(thing, &boardList[board].bFlag, B_UNSAVED);
}
CMDPROC(CmdErase) {
LWORD board;
BYTE buf[256];
BOARDMSG *boardMsg;
LWORD i;
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
cmd = StrOneWord(cmd, NULL);
if (!*cmd) {
SendThing("^rTry Erase <object> <msg #>\n", thing);
return;
}
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
found = CharThingFind(thing, srcKey, -1, thing, TF_OBJ, &srcOffset);
if (!found)
found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_OBJ, &srcOffset);
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return;
}
if (Obj(found)->oTemplate->oType!=OTYPE_BOARD) {
SendThing("^bThat sort of thing can have anything written on it.\n", thing);
return;
}
board = BoardOf(OBJECTGETFIELD(found, OF_BOARD_BVIRTUAL));
if (board == -1) {
SendThing("^wTell whoever created this thing that the virtual # is invalid\n", thing);
return;
}
/* check msg # */
i = -1;
sscanf(cmd, " %ld", &i);
i -= 1;
if (i<0 || i>= boardList[board].bIndex.iNum) {
SendThing("^wThere is no message with that number\n", thing);
return;
}
boardMsg = BoardMsg(boardList[board].bIndex.iThing[i]);
SendThing("^wErasing:\n", thing);
sprintf(buf, "^gMessage Number: ^G[^b%ld/%ld^G]\n", i+1, boardList[board].bIndex.iNum);
SendThing(buf, thing);
sprintf(buf, "^gAuthor: ^G[^b%s^G]\n", boardMsg->bAuthor->sText);
SendThing(buf, thing);
SendThing( "^gMessage Title: ^G[^g", thing);
SendThing(boardMsg->bTitle->sText, thing);
SendThing("^G]\n", thing);
BoardMsgDelete(board, i);
}
int InvScan(THING *thing, THING *scanner, BYTE *cmd) {
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
THING *search;
FLAG cFlag;
LWORD cValue;
FLAG sFlag;
LWORD sBio;
LWORD sMax;
LWORD sChip;
LWORD sLeft;
BYTE buf[256];
THING *world;
if (!*cmd) {
SendThing("^wPerhaps you should specify something to scan\n", thing);
return TRUE;
}
/* Scan, yes fine but What? */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
search = Base(thing)->bInside;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ, &srcOffset);
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return TRUE;
}
while (found && srcNum!=0) {
/* Scan Found */
while(1) {
if (found->tType != TTYPE_OBJ
||Obj(found)->oTemplate->oType != OTYPE_CONTAINER) {
SendThing("^pYou detect nothing of any particular interest\n", thing);
break;
}
cFlag = OBJECTGETFIELD(found, OF_CONTAINER_CFLAG);
cValue = OBJECTGETFIELD(found, OF_CONTAINER_SVALUE);
if (!BIT(cFlag, OCF_CORPSE)) {
SendThing("^CYou detect nothing of any particular interest\n", thing);
break;
}
/* Check out their scanner */
sFlag = OBJECTGETFIELD(scanner, OF_SCANNER_SFLAG);
sMax = OBJECTGETFIELD(scanner, OF_SCANNER_MAX);
sBio = OBJECTGETFIELD(scanner, OF_SCANNER_BIO);
sChip = OBJECTGETFIELD(scanner, OF_SCANNER_CHIP);
sLeft = sMax - sBio - sChip;
/* Check if they can do that */
if (BIT(cFlag, OCF_ELECTRONIC)) {
if (!BIT(sFlag, OSF_SCANCHIP)) {
SendThing("^wI'm afraid your scanner isnt capable of scanning that\n", thing);
break;
}
} else {
if (!BIT(sFlag, OSF_SCANBIO)) {
SendThing("^wI'm afraid your scanner isnt capable of scanning that\n", thing);
break;
}
}
/* Check if they have room */
if (sLeft < cValue) {
SendThing("^wI'm afraid your scanner doesnt have enough memory free to scan that\n", thing);
break;
}
SendAction("^wYou scan ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^C$n scans ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
/* guard against no gain zones etc here */
world = Base(thing)->bInside;
OBJECTSETFIELD(found, OF_CONTAINER_SVALUE, 0);
if (BIT(cFlag, OCF_ELECTRONIC)) {
sChip += cValue;
if (world->tType==TTYPE_WLD
&& BIT(areaList[Wld(world)->wArea].aResetFlag, RF_NOMONEY)) {
sprintf(buf, "^YYou ^rwould ^Yhave obtained ^y%ld ^Ycredits worth of chip technology\n", cValue);
} else {
OBJECTSETFIELD(scanner, OF_SCANNER_CHIP, sChip);
sprintf(buf, "^YYou obtain ^y%ld ^Ycredits worth of chip technology\n", cValue);
}
} else {
sBio += cValue;
if (world->tType==TTYPE_WLD
&& BIT(areaList[Wld(world)->wArea].aResetFlag, RF_NOMONEY)) {
sprintf(buf, "^YYou ^rwould ^Yhave obtained ^y%ld ^Ycredits worth of biological data\n", cValue);
} else {
OBJECTSETFIELD(scanner, OF_SCANNER_BIO, sBio);
sprintf(buf, "^YYou obtain ^y%ld ^Ycredits worth of biological data\n", cValue);
}
}
SendThing(buf, thing);
if (!cValue) {
SendThing("^wArgh! Nothing left worth scanning, someone beat you to it\n", thing);
}
break;
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
return TRUE;
}
/* for now we'll just make it so ya gotta hold it ta use it... */
CMDPROC(CmdUse) { /* void CmdProc(THING *thing, BYTE* cmd) */
BYTE srcKey[256];
LWORD srcNum;
LWORD srcOffset;
THING *found;
THING *search;
LWORD apply;
LWORD aType;
LWORD aValue;
THING *ammo = NULL;
LWORD ammoType;
LWORD ammoUse;
LWORD ammoLeft;
LWORD success;
cmd = StrOneWord(cmd, NULL); /* lose the command at the start */
cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL);
search = thing;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ, &srcOffset);
if (!found) {
search = Base(thing)->bInside;
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ, &srcOffset);
}
if (!found) {
SendThing("^bThere doesnt appear to be anything like that around\n", thing);
return;
}
while (found && srcNum!=0) {
ammo = ObjectGetAmmo(found, &ammoType, &ammoUse, &ammoLeft);
/* Block if this is carry2use and we're not carrying it */
if (BIT(Obj(found)->oAct, OA_CARRY2USE) && search != thing) {
SendAction("^wI'm afraid you must be carrying that to use it.\n",
thing, found, SEND_SRC|SEND_CAPFIRST);
}
/* Block if we are out of ammo */
else if (ammoType && !ammo) {
SendAction("^wI'm afraid ^g$N is unloaded\n",
thing, found, SEND_SRC|SEND_CAPFIRST);
}
else if (ammoUse > ammoLeft) {
SendAction("^wI'm afraid ^g$N just ran outta steam\n",
thing, found, SEND_SRC|SEND_CAPFIRST);
}
/* Give code Parser a crack at this */
else if (!CodeParseUse(thing, found)) {
/* Send they use the item message */
SendAction("^bYou use ^g$N\n",
thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST);
SendAction("^b$n uses ^g$N\n",
thing, found, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
success = FALSE;
/* Perform the objects actions */
for (apply=0; apply < OBJECT_MAX_APPLY; apply++) {
aType = Obj(found)->oApply[apply].aType;
aValue = Obj(found)->oApply[apply].aValue;
success |= Effect(applyList[aType].aEffect, applyList[aType].aTarget, thing, cmd, aValue);
}
/* Special actions due to the object type */
switch (Obj(found)->oTemplate->oType) {
case OTYPE_SCANNER:
/* Find the target etc, should I do this with an effect? */
success |= InvScan(thing, found, cmd);
break;
case OTYPE_DRUG:
if (thing->tType == TTYPE_PLR) {
Plr(thing)->pIntox += OBJECTGETFIELD(found, OF_DRUG_INTOX);
MAXSET(Plr(thing)->pIntox, raceList[Plr(thing)->pRace].rMaxIntox);
success = TRUE;
}
break;
}
/* after the fact script code */
success |= CodeParseAfterUse(thing, found);
/* affect align if good or evil */
if (success && thing->tType==TTYPE_PLR) {
if (BIT(Obj(found)->oAct, OA_EVIL)) {
if (Character(thing)->cAura > 400) {
Character(thing)->cAura -=1;
}
}
if (BIT(Obj(found)->oAct, OA_GOOD)) {
if (Character(thing)->cAura < -400) {
Character(thing)->cAura +=1;
}
}
}
/* tweak ammo / destroy object */
if (!success) {
SendAction("^wBut nothing much seems to happen\n",
thing, found, SEND_SRC|SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST);
} else if (!ammo) {
/* Destroy object or decrement ammo */
if (ammoUse>=0) THINGFREE(found);
} else {
ObjectUseAmmo(found);
}
}
/* see if there is more (will not find successive matches unless offset is TF_ALLMATCH) */
found = CharThingFind(thing, srcKey, -1, search, TF_OBJ|TF_CONTINUE, &srcOffset);
if (srcNum>0) srcNum--;
}
}