/* 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 */ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include <time.h> #include "crimson2.h" #include "macro.h" #include "log.h" #include "str.h" #include "property.h" #include "queue.h" #include "send.h" #include "parse.h" #include "thing.h" #include "exit.h" #include "world.h" #include "base.h" #include "char.h" #include "group.h" #include "mobile.h" #include "player.h" #include "affect.h" #include "object.h" #include "fight.h" #include "skill.h" #include "effect.h" #include "cmd_move.h" #include "cmd_cbt.h" /* look for something to kill along the lines of <key> <direction> */ /* synonymous with shoot, kill */ CMDPROC(CmdHit) { /*(THING *thing, BYTE *cmd)*/ BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *target; EXIT *exit; BYTE dir[256]; LWORD range = 1; /* 1 is inside the same room, thus a weapon with a range of 0 isnt very usefull */ cmd = StrOneWord(cmd, NULL); cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); target = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &srcOffset); if (!target) { SendThing("^wWho was that again?\n", thing); return; } if (target->tType==TTYPE_PLR) { if (thing->tType==TTYPE_PLR && Character(thing)->cLevel<6) { SendThing("^wYou must be at least 6th level before you may attack other players\n", thing); return; } } if (target) { FightStart(thing, target, 1, NULL); return; } /* the following is for ranged attacks */ return; /* Look to see if they are aiming somewhere */ cmd = StrOneWord(cmd, dir); if (!*dir) return; if (!Character(thing)->cWeapon) return; if (Character(thing)->cWeapon->tType != TTYPE_OBJ) return; if (Obj(Character(thing)->cWeapon)->oTemplate->oType != OTYPE_WEAPON) return; exit = ExitFind(Wld(Base(thing)->bInside)->wExit, dir); while (exit) { range++; if (range > OBJECTGETFIELD(Character(thing)->cWeapon, OF_WEAPON_RANGE)) break; target = CharThingFind(thing, srcKey, -1, exit->eWorld, TF_PLR|TF_MOB, &srcOffset); if (target) { FightStart(thing, target, 1, NULL); return; } exit = ExitDir(Wld(exit->eWorld)->wExit, exit->eDir); } } /* Add/Remove/View Current Group */ /* It would be cool if this tacked: Re, As, Lo etc combat related * flags after group members names */ CMDPROC(CmdGroup) { /*(THING *thing, BYTE *cmd)*/ BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *target; BYTE buf[256]; BYTE share[256]; LWORD followLevel = 0; LWORD followNumber = 0; THING *i; THING *tree[CHAR_MAX_FOLLOW]; LWORD treePos; LWORD j; LWORD skip; cmd = StrOneWord(cmd, NULL); if (!*cmd) { if (!Character(thing)->cLead) { SendThing("You're not IN a group\n", thing); return; } /* We're going to print them a pretty picture of their group. */ /* Collect Statistics on the group */ GroupGetStat(thing,&followNumber,&followLevel); /* Show them the group */ SendThing("^cGroup Member ^gLevel XP Share Hits Move Power\n", thing); SendThing("^C-+-+-+-+-+-+ ^G-+-+- +-+-+-+- -+-+ -+-+ -+-+-\n", thing); /* ok, the stuff to follow involves recursion. That's why it's * so complicated. */ tree[0]=GroupGetHighestLeader(thing); tree[1]=tree[0]; treePos=1; skip=0; do { /* let's print everyone at this level by this leader. */ for (; tree[treePos]; tree[treePos]=Character(tree[treePos])->cFollow) { if (Character(tree[treePos])->cLead==tree[treePos-1]) { /* print this character */ for (j=0;j<(treePos-1);j++) SendThing(" ", thing); i=tree[treePos]; if (GroupIsGroupedMember(tree[treePos],thing)) { sprintf(share, "%ld%%", Character(i)->cLevel*100/followLevel); sprintf(buf,"^c%-15s",i->tSDesc->sText); SendThing(buf,thing); for (j=0;j<(7-treePos);j++) SendThing(" ", thing); sprintf(buf, "^g%-5hd %-8s %-5ld %-5ld %-5ld ", Character(i)->cLevel, share, Character(i)->cHitP, Character(i)->cMoveP, Character(i)->cPowerP); if (i->tType == TTYPE_PLR) { if (BIT(Plr(i)->pAuto, PA_AUTOLOOT)) strcat(buf, "Lo"); if (BIT(Plr(i)->pAuto, PA_AUTOAGGR)) strcat(buf, "Ag"); if (BIT(Plr(i)->pAuto, PA_AUTORESCUE)) strcat(buf, "Re"); if (BIT(Plr(i)->pAuto, PA_AUTOASSIST)) strcat(buf, "As"); } else if (i->tType == TTYPE_MOB) { if (BIT(Mob(i)->mTemplate->mAct, MACT_RESCUE)) strcat(buf, "Re"); if (BIT(Mob(i)->mTemplate->mAct, MACT_AGGRESSIVE)) strcat(buf, "Ag"); if (BIT(Mob(i)->mTemplate->mAct, MACT_SCAVENGER)) strcat(buf, "Sc"); } strcat(buf, "\n"); } else { sprintf(buf,"^C%-15s",i->tSDesc->sText); SendThing(buf,thing); for (j=0;j<(7-treePos);j++) SendThing(" ", thing); sprintf(buf,"^W<NOT GROUPED>\n"); } SendThing(buf,thing); /* check if we need to recurse deeper */ if (GroupIsLeader(tree[treePos])&&(tree[treePos]!=tree[treePos-1])){ treePos++; tree[treePos]=GroupGetHighestLeader(thing); skip=1; break; } } } if (!skip) { treePos--; tree[treePos]=Character(tree[treePos])->cFollow; } skip=0; } while(treePos>0); /* if (i == GroupGetHighestLeader(i)) { if (BIT(Character(i)->cAffectFlag, AF_GROUP)) { if (BIT(Character(thing)->cAffectFlag, AF_GROUP)) { sprintf(share, "%ld%%", Character(i)->cLevel*100/followLevel); sprintf(buf, "^c%-20s ^g%-5hd %-8s %-5ld %-5ld %-5ld ", i->tSDesc->sText, Character(i)->cLevel, share, Character(i)->cHitP, Character(i)->cMoveP, Character(i)->cPowerP); if (i->tType == TTYPE_PLR) { if (BIT(Plr(i)->pAuto, PA_AUTOLOOT)) strcat(buf, "Lo"); if (BIT(Plr(i)->pAuto, PA_AUTOAGGR)) strcat(buf, "Ag"); if (BIT(Plr(i)->pAuto, PA_AUTORESCUE)) strcat(buf, "Re"); if (BIT(Plr(i)->pAuto, PA_AUTOASSIST)) strcat(buf, "As"); } else if (i->tType == TTYPE_MOB) { if (BIT(Mob(i)->mTemplate->mAct, MACT_RESCUE)) strcat(buf, "Re"); if (BIT(Mob(i)->mTemplate->mAct, MACT_AGGRESSIVE)) strcat(buf, "Ag"); if (BIT(Mob(i)->mTemplate->mAct, MACT_SCAVENGER)) strcat(buf, "Sc"); } strcat(buf, "\n"); } else { sprintf(buf, "^c%-20s ^w<GROUPED>\n", i->tSDesc->sText); } } else { sprintf(buf, "^c%-20s ^w<NOT GROUPED>\n", i->tSDesc->sText); } } else if (Character(i)->cLead==thing) { sprintf(buf, "^c%-20s ^y<FOLLOWING YOU>\n", i->tSDesc->sText); } else if (Character(i)->cLead==i) { sprintf(buf, "^c%-20s ^y<LEADING>\n", i->tSDesc->sText); } else if (i==Character(thing)->cLead && Character(i)->cLead) { sprintf(buf, "^c%-20s ^p<FOLLOWING> %s, <LEADING YOU>\n", i->tSDesc->sText, Character(i)->cLead->tSDesc->sText); } else if (Character(i)->cLead) { sprintf(buf, "^c%-20s ^p<FOLLOWING> %s\n", i->tSDesc->sText, Character(i)->cLead->tSDesc->sText); } else buf[0]=0; if (buf[0]) SendThing(buf, thing); }*/ sprintf(buf, "\n^wPeople in Group: ^c%ld, ^wTotal Level: ^c%ld\n", followNumber, followLevel); SendThing(buf, thing); return; } /* add or remove target as appropriate */ cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); target = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &srcOffset); if (target) { if (Character(target)->cLead != thing) { SendThing("They're not following you\n", thing); } else if (target==thing) { SendThing("You are always grouped within the group you lead\n", thing); } else { BITFLIP(Character(target)->cAffectFlag, AF_GROUP); if (!GroupVerifySize(thing)) { BITFLIP(Character(target)->cAffectFlag, AF_GROUP); SendAction("You cannout group $N: your group would be too big!\n", thing, target, SEND_SRC|SEND_CAPFIRST); SendAction("$n tried to group you but failed: $n's group would be too big!\n", thing, target, SEND_DST|SEND_VISIBLE|SEND_CAPFIRST); SendAction("$n tried to group $N but failed: $n's group would be too big!\n", thing, target, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); return; } if (BIT(Character(target)->cAffectFlag, AF_GROUP)) { SendAction("You add $N to your group\n", thing, target, SEND_SRC |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n adds you to $s group\n", thing, target, SEND_DST |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n adds $N to $s group\n", thing, target, SEND_ROOM|SEND_AUDIBLE|SEND_CAPFIRST); } else { SendAction("You kick $N out of your group\n", thing, target, SEND_SRC |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n kicks you out of $s group\n", thing, target, SEND_DST |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n kicks $N out of $s group\n", thing, target, SEND_ROOM|SEND_AUDIBLE|SEND_CAPFIRST); } } } } /* Follow / Unfollow somebody */ CMDPROC(CmdFollow) { /*(THING *thing, BYTE *cmd)*/ BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *target; /* * Should check for domination here, the dominated cant change who * they are following */ cmd = StrOneWord(cmd, NULL); /* Stop following */ if (!*cmd) { if ((!Character(thing)->cLead) || (Character(thing)->cLead==thing)) { SendThing("^wYes, but who do you want to follow...\n", thing); return; } SendAction("You stop following $N\n", thing, Character(thing)->cLead, SEND_SRC |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n stops following you\n", thing, Character(thing)->cLead, SEND_DST |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n stops following $N\n", thing, Character(thing)->cLead, SEND_ROOM|SEND_AUDIBLE|SEND_CAPFIRST); CharRemoveFollow(thing); return; } /* Follow the target */ cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); target = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &srcOffset); if (target) { if (target == thing) { SendThing("^wYou start to follow yourself\n", thing); CharRemoveFollow(thing); return; } if (CharAddFollow(thing, target)) { SendAction("You start following $N\n", thing, Character(thing)->cLead, SEND_SRC |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n starts following you\n", thing, Character(thing)->cLead, SEND_DST |SEND_AUDIBLE|SEND_CAPFIRST); SendAction("$n starts following $N\n", thing, Character(thing)->cLead, SEND_ROOM|SEND_AUDIBLE|SEND_CAPFIRST); } else { SendThing("I'm afraid they've got too many followers allready\n", thing); } } } /* * I could make this so that it pulls the text out of the skill table, * but I'd rather have the minor annoyance of double-entering the text * than a non-standard text lookup method */ struct PsiListType psiList[] = { /* Body */ { "Cell-Repair", &SKILL_CELL_REPAIR, EFFECT_CELL_REPAIR, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Refresh", &SKILL_REFRESH, EFFECT_REFRESH, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Endurance", &SKILL_ENDURANCE, EFFECT_ENDURANCE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Breathwater", &SKILL_BREATHWATER, EFFECT_BREATHWATER, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Strength", &SKILL_STRENGTH, EFFECT_STRENGTH, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Darkvision", &SKILL_DARKVISION, EFFECT_DARKVISION, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Slow-Poison", &SKILL_SLOW_POISON, EFFECT_SLOW_POISON, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Cure-Poison", &SKILL_CURE_POISON, EFFECT_CURE_POISON, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Heal-Minor", &SKILL_HEAL_MINOR, EFFECT_HEAL_MINOR, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Regeneration", &SKILL_REGENERATION, EFFECT_REGENERATION, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Heal-Major", &SKILL_HEAL_MAJOR, EFFECT_HEAL_MAJOR, 100,25, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Dexterity", &SKILL_DEXTERITY, EFFECT_DEXTERITY, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Constitution", &SKILL_CONSTITUTION, EFFECT_CONSTITUTION, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Haste", &SKILL_HASTE, EFFECT_HASTE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Quench", &SKILL_QUENCH, EFFECT_QUENCH, 50, 5, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Sustenance", &SKILL_SUSTENANCE, EFFECT_SUSTENANCE, 50, 5, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Acidtouch", &SKILL_ACIDTOUCH, EFFECT_ACIDTOUCH, 70, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Poisontouch", &SKILL_POISONTOUCH, EFFECT_POISONTOUCH, 70, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, /* Telekinetic */ { "Crush", &SKILL_CRUSH, EFFECT_CRUSH, 60, 20, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Forcestorm", &SKILL_FORCESTORM, EFFECT_FORCESTORM, 60, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Ghostfist", &SKILL_GHOSTFIST, EFFECT_GHOSTFIST, 60, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Kinetic-Shield", &SKILL_KINETIC_SHIELD,EFFECT_KINETIC_SHIELD,50,15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Immobilize", &SKILL_IMMOBILIZE, EFFECT_IMMOBILIZE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Heartstop", &SKILL_HEARTSTOP, EFFECT_HEARTSTOP, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Asphyxiate", &SKILL_ASPHYXIATE, EFFECT_ASPHYXIATE, 50, 15, }, { "Invisibility", &SKILL_INVISIBILITY, EFFECT_INVISIBILITY, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Slow", &SKILL_SLOW, EFFECT_SLOW, 50, 5, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "ImprovedInvis", &SKILL_IMPROVEDINVIS, EFFECT_IMPROVEDINVIS,75, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Vacuumwalk", &SKILL_VACUUMWALK, EFFECT_VACUUMWALK, 50, 15, TAR_SELF_DEF}, /* Telepathy */ { "PhantomEar", &SKILL_PHANTOMEAR, EFFECT_PHANTOMEAR, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_NODEFAULT}, { "PhantomEye", &SKILL_PHANTOMEYE, EFFECT_PHANTOMEYE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_NODEFAULT}, { "Mindlink", &SKILL_MINDLINK, EFFECT_MINDLINK, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_NODEFAULT}, { "Domination", &SKILL_DOMINATION, EFFECT_DOMINATION, 75, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_NODEFAULT}, { "Thoughtblade", &SKILL_THOUGHTBLADE, EFFECT_THOUGHTBLADE, 50, 5, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Mindcrush", &SKILL_MINDCRUSH, EFFECT_MINDCRUSH, 55, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Deathdream", &SKILL_DEATHDREAM, EFFECT_DEATHDREAM, 60, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Mindshield", &SKILL_MINDSHIELD, EFFECT_MINDSHIELD, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Sleep", &SKILL_SLEEP, EFFECT_SLEEP, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_NODEFAULT}, { "Berserk", &SKILL_BERSERK, EFFECT_BERSERK, 99, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Mindclear", &SKILL_MINDCLEAR, EFFECT_MINDCLEAR, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, /* Apportation */ { "Teleport", &SKILL_TELEPORT, EFFECT_TELEPORT, 99, 25, TAR_SELF_DEF }, { "Summon", &SKILL_SUMMON, EFFECT_SUMMON, 99, 25, TAR_PLR_WLD|TAR_MOB_WLD }, { "Succor", &SKILL_SUCCOR, EFFECT_SUCCOR, 99, 25, TAR_SELF_DEF}, { "Banish", &SKILL_BANISH, EFFECT_BANISH, 99, 25, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "MassTeleport", &SKILL_MASSTELEPORT, EFFECT_TELEPORT, 99, 25, TAR_GROUP_DEF }, { "MassSuccor", &SKILL_MASSSUCCOR, EFFECT_SUCCOR, 99, 25, TAR_SELF_DEF|TAR_GROUPWLD_DEF }, { "MassSummon", &SKILL_MASSSUMMON, EFFECT_SUMMON, 99, 25, TAR_SELF_DEF|TAR_GROUPWLD_DEF }, { "DisruptDoor", &SKILL_DISRUPTDOOR, EFFECT_DISRUPTDOOR, 50, 15, }, { "PhaseDoor", &SKILL_PHASEDOOR, EFFECT_PHASEDOOR, 50, 15, }, { "Phasewalk", &SKILL_PHASEWALK, EFFECT_PHASEWALK, 50, 15, TAR_SELF_DEF}, { "Phantompocket", &SKILL_PHANTOMPOCKET, EFFECT_PHANTOMPOCKET,75, 25, TAR_SELF_DEF}, { "Waterwalk", &SKILL_WATERWALK, EFFECT_WATERWALK, 50, 15, TAR_SELF_DEF}, { "Teletrack", &SKILL_TELETRACK, EFFECT_TELETRACK, 75, 25, TAR_PLR_WLD|TAR_MOB_WLD}, { "Recall", &SKILL_RECALL, EFFECT_RECALL, 75, 25, TAR_SELF_DEF }, { "Mark", &SKILL_MARK, EFFECT_MARK, 75, 25, TAR_SELF_DEF }, { "Translocate", &SKILL_TRANSLOCATE, EFFECT_TRANSLOCATE, 99, 30, TAR_SELF_DEF }, /* Spirit */ { "Spiritwalk", &SKILL_SPIRITWALK, EFFECT_SPIRITWALK, 50, 15, TAR_SELF_DEF }, { "SenseLife", &SKILL_SENSELIFE, EFFECT_SENSELIFE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF }, { "SeeInvisible", &SKILL_SEEINVISIBLE, EFFECT_SEEINVISIBLE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF }, { "LuckShield", &SKILL_LUCKSHIELD, EFFECT_LUCKSHIELD, 99, 25, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF }, { "Identify", &SKILL_IDENTIFY, EFFECT_IDENTIFY, 150, 50, TAR_OBJ_ROOM|TAR_OBJ_INV }, { "Stat", &SKILL_STAT, EFFECT_STAT, 150, 50, TAR_PLR_ROOM|TAR_MOB_ROOM }, { "Luckyhits", &SKILL_LUCKYHITS, EFFECT_LUCKYHITS, 99, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF }, { "Luckydamage", &SKILL_LUCKYDAMAGE, EFFECT_LUCKYDAMAGE, 99, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF }, /* Pyrokinetic */ { "BurningFist", &SKILL_BURNINGFIST, EFFECT_BURNINGFIST, 50, 5, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "FlameStrike", &SKILL_FLAMESTRIKE, EFFECT_FLAMESTRIKE, 55, 10, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Incinerate", &SKILL_INCINERATE, EFFECT_INCINERATE, 60, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Ignite", &SKILL_IGNITE, EFFECT_IGNITE, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_FIGHT_DEF}, { "Heatshield", &SKILL_HEATSHIELD, EFFECT_HEATSHIELD, 50, 15, TAR_PLR_ROOM|TAR_MOB_ROOM|TAR_SELF_DEF}, { "Fireblade", &SKILL_FIREBLADE, EFFECT_FIREBLADE, 75, 20, TAR_SELF_DEF}, { "Fireshield", &SKILL_FIRESHIELD, EFFECT_FIRESHIELD, 75, 20, TAR_SELF_DEF}, { "Firearmor", &SKILL_FIREARMOR, EFFECT_FIREARMOR, 75, 20, TAR_SELF_DEF}, { "", 0, 0, 0, 0, 0 } }; /* Cast spells/Concentrate psionics etc */ CMDPROC(CmdConcentrate) { /*(THING *thing, BYTE *cmd)*/ LWORD i; LWORD numShown; BYTE buf[256]; BYTE line[256]; LWORD cost; LWORD skill; #define SCALEFACTOR 50 /* throwaway concentrate */ cmd = StrOneWord(cmd, NULL); if (!*cmd) { SendThing("^wYes but the question remains, what should I cast... Your options are:\n", thing); numShown = 0; for(i=0; *psiList[i].pName; i++) { skill = CharGetSkill(thing, *(psiList[i].pSkill) ); if (skill) { if (thing->tType==TTYPE_PLR && Character(thing)->cLevel >= LEVEL_GOD) { cost = 0; } else { cost = psiList[i].pMaxCost*SCALEFACTOR/( skill + SCALEFACTOR ); MINSET(cost, psiList[i].pMinCost); MAXSET(cost, psiList[i].pMaxCost); } sprintf(line, "%s[%ld]", psiList[i].pName, cost); sprintf(buf,"%-19s", line); SendThing(buf, thing); numShown++; if (numShown%4 == 0) SendThing("\n", thing); } } if (numShown%4 != 0) SendThing("\n", thing); return; } /* get the next word - ie what they cast */ cmd = StrOneWord(cmd, buf); i = TYPEFIND(buf, psiList); if (i == -1) { SendThing("^wOh, good one... making this up as we go are we?", thing); return; } /* Can they cast it */ skill = CharGetSkill(thing, *(psiList[i].pSkill) ); if (skill <= 0) { SendThing("^rI'm afraid you're not very good at that sort of thing.\n", thing); return; } /* Calc Cost */ if (thing->tType==TTYPE_PLR && Character(thing)->cLevel >= LEVEL_GOD) { cost = 0; } else { cost = psiList[i].pMaxCost*SCALEFACTOR/( skill + SCALEFACTOR ); MINSET(cost, psiList[i].pMinCost); MAXSET(cost, psiList[i].pMaxCost); } if (Character(thing)->cPowerP < cost) { SendThing("^rI'm afraid you dont have enough energy left for that sort of thing.\n", thing); return; } /* produce an effect */ sprintf(buf, "^cYou concentrate briefly on ^g'%s' ^c(expending ^w%ld ^cpoints)\n", psiList[i].pName, cost); SendAction(buf, thing, NULL, SEND_SRC); SendAction("^c$n concentrates briefly.\n", thing, NULL, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); thing->tWait++; /* make it so they cant initiate a command for a "round" */ if (!Effect(psiList[i].pEffect, psiList[i].pTarget, thing, cmd, skill)) { SendThing("^wUmm, yeah okay, maybe you should specify a target for that\n", thing); return; } Character(thing)->cPowerP -= cost; } CMDPROC(CmdPractice) { /*(THING *thing, BYTE *cmd)*/ SkillShow(thing, cmd, 0xFFFFFFFF, 0, 0); /* Thing, Cmd, CanPractice, CantPractice, maxLevel */ /* Since MaxLevel is 0, it is display only and will * not allow any actual practicing to take place */ } void CbtConsider(THING *thing, THING *target) { LWORD relLevel = 1; if (!thing || !target) return; if (thing->tType<TTYPE_CHARACTER || target->tType<TTYPE_CHARACTER) return; relLevel = Character(target)->cLevel - Character(thing)->cLevel; /* Tough fight */ if (relLevel > 10) { SendThing("^wIt gives you the willies just thinking about it. Brrrr...\n", thing); } else if (relLevel > 5) { SendThing("^wWith a great group and a little luck you might be able to pull it off\n", thing); } else if (relLevel > 2) { SendThing("^wTheres safety in numbers, I wouldnt try this alone\n", thing); } else if (relLevel > 0) { SendThing("^wA little luck and you're there\n", thing); /* Equal Fight */ } else if (relLevel == 0) { SendThing("^wHeads you win.....\n", thing); /* Easy Fight */ } else if (relLevel < 10) { SendThing("^wSure you could do it, but why bother\n", thing); } else if (relLevel < 5) { SendThing("^wYou could take 'em in your sleep\n", thing); } else if (relLevel < 2) { SendThing("^wI dont think its going to put up too stiff a fight\n", thing); } else if (relLevel < 0) { SendThing("^wAs long as it doesnt have something up its sleeves\n", thing); } /* Warn if their weapon sucks */ } CMDPROC(CmdConsider) { /*(THING *thing, BYTE *cmd)*/ BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *target; cmd = StrOneWord(cmd, NULL); cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); target = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &srcOffset); if (!target) { SendThing("^wWho was that again?\n", thing); return; } CbtConsider(thing, target); } BYTE Flee(THING *thing) { EXIT *exit; LWORD exitNum; LWORD success = FALSE; LWORD check; /* additional movement point cost check here */ if (Character(thing)->cMoveP < 10) return FALSE; Character(thing)->cMoveP -= 10; check = DiceOpenEnded(1, 100, 100); if (thing->tType == TTYPE_PLR) { check += Plr(thing)->pSkill[SKILL_FLEE]; } else if (thing->tType == TTYPE_MOB) { check += PropertyGetLWord(thing, "%Flee", Mob(thing)->mTemplate->mLevel*2); } if (Character(thing)->cFight) { if (Character(thing)->cFight->tType == TTYPE_PLR) { check -= Plr(Character(thing)->cFight)->pSkill[SKILL_PURSUE]; } else if (Character(thing)->cFight->tType == TTYPE_MOB) { check -= PropertyGetLWord(Character(thing)->cFight, "%Pursue", Mob(Character(thing)->cFight)->mTemplate->mLevel*2); } } /* See if they made it */ if (check >= 50) { /* 50% chance of fleeing */ /* count exits */ for (exitNum=0,exit=Wld(Base(thing)->bInside)->wExit; exit; exit=exit->eNext) exitNum++; /* pick a random direction */ exitNum = Number(1,exitNum); for (exit=Wld(Base(thing)->bInside)->wExit; exit&&exitNum!=1; exit=exit->eNext,exitNum--); /* see if we can go this way */ if(exit && exit->eWorld) success = MoveExit(thing, exit); } if (!Character(thing)->cFight) { SendThing("^bAck, Eeek, panic, panic... ^P(^pWhat are we running from again?^P)\n", thing); } else if (!success) { SendThing("^wAck, Eeek, panic, panic... ^P(^bYOU COULDNT GET AWAY^P)\n", thing); } else { SendThing("^wRun Away! Run Away!\n", thing); } return success; } CMDPROC(CmdFlee) { /*(THING *thing, BYTE *cmd)*/ /* Check for code script interception */ if (!Flee(thing)) thing->tWait++; /* make it so they cant initiate a command for a "round" */ } BYTE CbtRescue(THING *thing, THING *target) { LWORD check; LWORD cost; if (!thing || !target || Base(target)->bInside!=Base(thing)->bInside) return FALSE; if (!Character(target)->cFight) { /* found somebody to rescue */ SendThing("^wThey're not in need of rescuing right now...\n", thing); return FALSE; } thing->tWait+=3; /* make it so theycant initiate a command for a "round" */ cost = RESCUE_MOVE_COST; cost = CharMoveCostAdjust(thing, cost); if (Character(thing)->cMoveP < cost) { /* failed the rescue */ SendAction("^YYou try to rescue $N, ^ybut are too exhausted!\n", thing, target, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to rescue you, ^ybut $h is too exhausted!!\n", thing, target, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to rescue $N, ^ybut is too exhausted!\n", thing, target, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); return FALSE; } Character(thing)->cMoveP -= cost; check = DiceOpenEnded(1, 100, 100); if (thing->tType == TTYPE_PLR) { check += Plr(thing)->pSkill[SKILL_RESCUE]; } else if (thing->tType == TTYPE_MOB) { check += PropertyGetLWord(thing, "%Rescue", Mob(thing)->mTemplate->mLevel*2); } if (Character(target)->cFight->tType == TTYPE_PLR) { check -= Plr(Character(target)->cFight)->pSkill[SKILL_PURSUE]; } else if (Character(target)->cFight->tType == TTYPE_MOB) { check -= PropertyGetLWord(Character(target)->cFight, "%Pursue", Mob(Character(target)->cFight)->mTemplate->mLevel*2); } else return FALSE; if (check >= 75) { /* Made the rescue */ SendAction("^yYou rescue $N\n", thing, target, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^y$n rescues you\n", thing, target, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^y$n rescues $N\n", thing, target, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); FightStart(thing, Character(target)->cFight, Character(target)->cFightRange, Character(target)->cFightExit); Character(Character(target)->cFight)->cFight = thing; Character(thing)->cFight = Character(target)->cFight; return TRUE; } else { /* failed the rescue */ SendAction("^YYou try to rescue $N, ^ybut FAIL!\n", thing, target, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to rescue you, ^ybut FAILS!\n", thing, target, SEND_DST |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to rescue $N, ^ybut FAILS!\n", thing, target, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); return FALSE; } } CMDPROC(CmdRescue) { /*(THING *thing, BYTE *cmd)*/ BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *target; cmd = StrOneWord(cmd, NULL); /* Stop following */ if (!*cmd) { SendThing("^wYes, but who do you want to rescue...\n", thing); return; } /* rescue the target */ cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); target = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_PLR|TF_MOB, &srcOffset); if (!target) { /* found somebody to rescue */ SendThing("^wWho did you want to rescue again?...\n", thing); return; } CbtRescue(thing, target); } CMDPROC(CmdHide) { /*(THING *thing, BYTE *cmd)*/ LWORD cost; LWORD check; if (BIT(Character(thing)->cAffectFlag, AF_HIDDEN)) { SendThing("^wBut you're allready hiding!\n", thing); return; } if (thing->tType == TTYPE_PLR && !Plr(thing)->pSkill[SKILL_HIDE]) { SendThing("^wI'm afraid you're not much good at this sort of thing\n", thing); return; } thing->tWait++; /* make it so theycant initiate a command for a "round" */ cost = HIDE_MOVE_COST; cost = CharMoveCostAdjust(thing, cost); if (Character(thing)->cMoveP < cost) { /* failed to hide */ SendAction("^YYou try to hide, ^ybut are too exhausted!\n", thing, NULL, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to hide, ^ybut is too exhausted!\n", thing, NULL, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); return; } Character(thing)->cMoveP -= cost; check = DiceOpenEnded(1, 100, 100); if (thing->tType == TTYPE_PLR) { check += Plr(thing)->pSkill[SKILL_HIDE]; } else if (thing->tType == TTYPE_MOB) { check += PropertyGetLWord(thing, "%Hide", Mob(thing)->mTemplate->mLevel*2); } if (check >= 75) { SendThing("^YYou disappear into the shadows\n", thing); /* Should probably tell everyone who makes a PERCEPTION check what just happened */ BITSET(Character(thing)->cAffectFlag, AF_HIDDEN); } else { SendAction("^YYou try to hide, ^ybut FAIL!\n", thing, NULL, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); SendAction("^Y$n tries to hide, ^ybut FAILS!\n", thing, NULL, SEND_ROOM|SEND_VISIBLE|SEND_CAPFIRST); } } /* Peek into someone elses inventory... naughty, naughty... */ CMDPROC(CmdPeek) { BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *found; LWORD cost; LWORD guard; LWORD perception; LWORD peek; LWORD check; THING *i; cmd = StrOneWord(cmd, NULL); if (!*cmd) { SendThing("^rTry Peek <Person>\n", thing); return; } cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); found = CharThingFind(thing, srcKey, -1, Base(thing)->bInside, TF_MOB|TF_PLR, &srcOffset); if (!found) { SendThing("^bThere doesnt appear to be anything like that around\n", thing); return; } thing->tWait+=3; /* make it so they cant initiate a command for a "round" */ cost = PEEK_MOVE_COST; cost = CharMoveCostAdjust(thing, cost); if (Character(thing)->cMoveP < cost) { /* failed to peek */ SendAction("^YYou try to peek into $N's inventory, ^ybut are too exhausted!\n", thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); return; } Character(thing)->cMoveP -= cost; /* get skills involved */ peek = CharGetPeek(thing); if (peek <= 0) { SendThing("^bYou've never bothered to learn how to do that\n", thing); return; } perception = CharGetPerception(found); guard = CharGetGuard(found); /* Guard against it */ check = DiceOpenEnded(1, 100, 100); if (perception + 50 > peek + check) { if (guard > peek) { SendAction("^YYou try to peek into $N's inventory, but they guard against it\n", thing, found, SEND_SRC |SEND_VISIBLE); SendAction("^YYou notice $n trying to peek into your inventory and guard against it\n", thing, found, SEND_DST |SEND_VISIBLE); return; } else { SendAction("^YYou notice $n trying to peek into your inventory\n", thing, found, SEND_DST |SEND_VISIBLE); peek -= guard; } /* If the mob we peeked is unfriendly to thieves attack them here */ if (found->tType == TTYPE_MOB && perception+50 > peek + check) { if (Number(1,100) < 10) FightStart(found, thing, 1, NULL); } } SendAction("^YYou try to peek into $N's inventory, and see:\n", thing, found, SEND_SRC |SEND_VISIBLE); for (i=found->tContain; i;) { check = DiceOpenEnded(1, 100, 100); check += peek; /* Peek has been adjusted for guard allready */ if (check >= 75 && i->tType==TTYPE_OBJ && !Obj(i)->oEquip) { /* Show them the item */ i = ThingShow(i, thing); } else i = i->tNext; } } /* Steal an item from someone's inventory */ CMDPROC(CmdSteal) { /* void CmdProc(THING *thing, BYTE* cmd) */ BYTE srcKey[256]; BYTE dstKey[256]; LWORD srcNum; LWORD srcOffset; LWORD dstOffset; THING *found; THING *search; THING *dest; LWORD guard; LWORD perception; LWORD steal; LWORD check; LWORD cost; THING *i; LWORD noticed = 0; 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 steal from\n", thing); return; } /* search them for an object */ search = dest; found = CharThingFind(thing, srcKey, -1, search, TF_OBJINV, &srcOffset); if (!found) { SendThing("^bThere doesnt appear to be anything like that on them to steal\n", thing); return; } /* get skills involved */ steal = CharGetSteal(thing); if (steal <= 0) { SendThing("^bYou've never bothered to learn how to do that\n", thing); return; } perception = CharGetPerception(dest); guard = CharGetGuard(dest); while (found && srcNum!=0) { thing->tWait+=3; /* make it so they cant initiate a command for a "round" */ cost = STEAL_MOVE_COST; cost = CharMoveCostAdjust(thing, cost); if (Character(thing)->cMoveP < cost) { SendAction("^YYou try to steal from $N's inventory, ^ybut are too exhausted!\n", thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); return; } Character(thing)->cMoveP -= cost; if (Base(found)->bWeight + Base(thing)->bConWeight > CharGetCarryMax(thing)) { SendAction("^CYou try to steal ^g$N", thing, found, SEND_SRC); SendAction("^Cfrom ^g$N^C, but its too heavy!\n", thing, dest, SEND_SRC); } else { check = DiceOpenEnded(1, 100, 100); if (perception + 50 >= steal + check) { /* They noticed */ steal -= guard; noticed += 1; } if (steal + check >= 75) { /* Steal succeeds */ for (i= Base(thing)->bInside->tContain; i; i=i->tNext) { perception = CharGetPerception(dest); if (i != thing && perception+50 > steal + check) { /* Someone noticed acts */ SendAction("^b$N ", i, thing, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST); SendAction("^bsteals ^g$N ", i, found, SEND_SRC|SEND_VISIBLE); SendAction("^bfrom ^g$N\n", i, dest, SEND_SRC|SEND_VISIBLE); noticed += 1; } } SendAction("^bYou steal ^g$N ", thing, found, SEND_SRC|SEND_CAPFIRST); SendAction("^bfrom ^g$N\n", thing, dest, SEND_SRC); ThingTo(found, thing); /* Infamy */ if (DiceOpenEnded(1, 100, 100) < noticed) { if (thing->tType==TTYPE_PLR) { BYTE buf[256]; sprintf(buf, "^yYou've been ^wcaught ^ystealing, you gain 1 point of ^wINFAMY^w!!\n"); SendThing(buf, thing); PlayerGainInfamy(thing, 1, buf); } } } else { /* Steal fails */ for (i= Base(thing)->bInside->tContain; i; i=i->tNext) { perception = CharGetPerception(i); if (i != thing && perception+50 > steal + check) { /* Someone noticed acts */ SendAction("^b$N ", i, thing, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST); SendAction("^btries to steal ^g$N ", i, found, SEND_SRC|SEND_VISIBLE); SendAction("^bfrom ^g$N^w and FAILS!\n", i, dest, SEND_SRC|SEND_VISIBLE); noticed += 1; } } SendAction("^bYou try to steal ^g$N ", thing, found, SEND_SRC|SEND_CAPFIRST); SendAction("^bfrom ^g$N ^wand FAIL!\n", thing, dest, SEND_SRC); /* Infamy */ if (DiceOpenEnded(1, 100, 100) < noticed/2) { if (thing->tType==TTYPE_PLR) { BYTE buf[256]; sprintf(buf, "^yYou've been ^wcaught ^ystealing, you gain 1 point of ^wINFAMY^w!!\n"); SendThing(buf, thing); PlayerGainInfamy(thing, 1, buf); } } /* If the mob we steal from is unfriendly to thieves attack them here */ if (dest->tType == TTYPE_MOB && perception+50 > steal + check) { FightStart(dest, thing, 1, NULL); } } } /* 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--; } } /* Steal an item from someone's inventory */ CMDPROC(CmdPickpocket) { /* void CmdProc(THING *thing, BYTE* cmd) */ BYTE buf[256]; BYTE srcKey[256]; LWORD srcNum; LWORD srcOffset; THING *found; THING *search; LWORD guard; LWORD perception; LWORD pickpocket; LWORD check; LWORD cost; LWORD amount; THING *i; cmd = StrOneWord(cmd, NULL); /* lose the command at the start */ cmd = ParseFind(cmd, srcKey, &srcOffset, &srcNum, NULL, NULL); /* search the room for a target */ search = Base(thing)->bInside; if (*srcKey) { found = CharThingFind(thing, srcKey, -1, search, TF_PLR|TF_MOB, &srcOffset); } else found = NULL; if (!found) { SendThing("^bThere doesnt appear to be anyone like that to pickpocket\n", thing); return; } /* get skills involved */ pickpocket = CharGetPickpocket(thing); if (pickpocket <= 0) { SendThing("^bYou've never bothered to learn how to do that\n", thing); return; } perception = CharGetPerception(found); guard = CharGetGuard(found); while (found && srcNum!=0) { thing->tWait+=3; /* make it so they cant initiate a command for a "round" */ cost = PICKPOCKET_MOVE_COST; cost = CharMoveCostAdjust(thing, cost); if (Character(thing)->cMoveP < cost) { SendAction("^YYou try to pickpocket $N, ^ybut are too exhausted!\n", thing, found, SEND_SRC |SEND_VISIBLE|SEND_CAPFIRST); return; } Character(thing)->cMoveP -= cost; check = DiceOpenEnded(1, 100, 100); if (perception + 50 >= pickpocket + check) { /* They noticed */ pickpocket -= guard; } if (pickpocket + check >= 75) { /* Steal succeeds */ for (i= Base(thing)->bInside->tContain; i; i=i->tNext) { perception = CharGetPerception(found); if (i != thing && perception+50 > pickpocket + check) { /* Someone noticed acts */ SendAction("^b$N ", i, thing, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST); SendAction("^bpicks ^g$N's pocket\n", i, found, SEND_SRC|SEND_VISIBLE); } } SendAction("^bYou pick ^g$N's ^bpocket ", thing, found, SEND_SRC|SEND_CAPFIRST); /* Take some money */ if (Character(found)->cMoney == 0) { SendAction("but they're broke!\n", thing, found, SEND_SRC); } else { amount = Number(1, MAXV(1,pickpocket*3)); MAXSET(amount, Character(found)->cMoney); Character(found)->cMoney -= amount; Character(thing)->cMoney += amount; sprintf(buf, "and get ^w%ld ^bcredits\n", amount); SendAction(buf, thing, found, SEND_SRC); } } else { /* Pickpocket fails */ for (i= Base(thing)->bInside->tContain; i; i=i->tNext) { perception = CharGetPerception(i); if (i != thing && perception+50 > pickpocket + check) { /* Someone noticed acts */ SendAction("^b$N ", i, thing, SEND_SRC|SEND_VISIBLE|SEND_CAPFIRST); SendAction("^btries to pickpocket ^g$N^w and FAILS!\n", i, found, SEND_SRC|SEND_VISIBLE); } } SendAction("^bYou try to pickpocket ^g$N ^wand FAIL!\n", thing, found, SEND_SRC); /* If the mob we pickpocket is unfriendly to thieves attack them here */ if (found->tType == TTYPE_MOB && perception+50 > pickpocket + check) { FightStart(found, thing, 1, NULL); } } /* 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--; } }