int do_give(int cn,int dir) { int m,x,y,co,in; struct misc_ppd *ppd; if (cn<1 || cn>=MAXCHARS) { error=ERR_ILLEGAL_CHARNO; return 0; } if (ch[cn].flags&(CF_DEAD)) { error=ERR_DEAD; return 0; } if (!(in=ch[cn].citem)) { error=ERR_NO_CITEM; return 0; } if (in<1 || in>=MAXITEM) { elog("do_give(): item number %d in citem of %s (%d) is out of bounds.",in,ch[cn].name,cn); ch[cn].citem=0; error=ERR_CONFUSED; return 0; } if (!dx2offset(dir,&x,&y,NULL)) { error=ERR_ILLEGAL_DIR; return 0; } x+=ch[cn].x; y+=ch[cn].y; if (x<1 || x>=MAXMAP || y<1 || y>=MAXMAP) { error=ERR_ILLEGAL_COORDS; return 0; } m=x+y*MAXMAP; if (!(co=map[m].ch)) { error=ERR_NO_CHAR; return 0; } if (ch[co].flags&CF_DEAD) { error=ERR_DEAD; return 0; } if (ch[co].flags&CF_NOGIVE) { error=ERR_QUESTITEM; return 0; } if ((it[in].flags&IF_QUEST) && !(ch[co].flags&(CF_QUESTITEM|CF_GOD)) && !(ch[cn].flags&(CF_QUESTITEM|CF_GOD))) { error=ERR_QUESTITEM; return 0; } if ((it[in].flags&IF_BONDTAKE) && ((ch[cn].flags&CF_GOD) || (ch[co].flags&CF_GOD))) { it[in].ownerID=ch[co].ID; } if (!can_carry(co,in,1)) return 0; if ((ch[co].flags&CF_PLAYER) && ch[co].citem && cnt_free_inv(co)<1) { error=ERR_BLOCKED; return 0; } if (!(ch[co].flags&CF_PLAYER) && ch[co].citem) { error=ERR_BLOCKED; return 0; } if ((ch[cn].flags&CF_PLAYER) && (ch[co].flags&CF_PLAYER) && (ppd=set_data(co,DRD_MISC_PPD,sizeof(struct misc_ppd))) && realtime-ppd->swapped<20) { log_char(cn,LOG_SYSTEM,0,"°c3Give canceled: Your target has swapped recently."); error=ERR_ACCESS_DENIED; return 0; } ch[cn].action=AC_GIVE; ch[cn].act1=co; ch[cn].duration=speed(ch[cn].value[0][V_SPEED],ch[cn].speed_mode,DUR_MISC_ACTION); if (ch[cn].speed_mode==SM_FAST) ch[cn].endurance-=end_cost(cn); ch[cn].dir=dir; return 1; }
void itemspawn(int in,int cn) { int in2; if (!cn) return; // always make sure its not an automatic call if you don't handle it if (ch[cn].citem) { log_char(cn,LOG_SYSTEM,0,"Please empty your 'hand' (mouse cursor) first."); return; } // get item to spawn switch(it[in].drdata[0]) { case 0: in2=create_item("melting_key"); break; case 1: in2=create_item("ice_boots1"); break; case 2: in2=create_item("ice_cape1"); break; case 3: in2=create_item("ice_belt1"); break; case 4: in2=create_item("ice_ring1"); break; case 5: in2=create_item("ice_amulet1"); break; case 6: in2=create_item("melting_key2"); break; case 7: in2=create_item("ice_boots2"); break; case 8: in2=create_item("ice_cape2"); break; case 9: in2=create_item("ice_belt2"); break; case 10: in2=create_item("ice_ring2"); break; case 11: in2=create_item("ice_amulet2"); break; case 12: in2=create_item("ice_boots3"); break; case 13: in2=create_item("ice_cape3"); break; case 14: in2=create_item("ice_belt3"); break; case 15: in2=create_item("ice_ring3"); break; case 16: in2=create_item("ice_amulet3"); break; case 17: in2=create_item("palace_bomb"); break; case 18: in2=create_item("palace_cap"); break; default: log_char(cn,LOG_SYSTEM,0,"Congratulations, %s, you have just discovered bug #4244B-%d-%d, please report it to the authorities!",ch[cn].name,it[in].x,it[in].y); return; } if (!in2) { log_char(cn,LOG_SYSTEM,0,"Congratulations, %s, you have just discovered bug #4244C-%d-%d, please report it to the authorities!",ch[cn].name,it[in].x,it[in].y); return; } if (!can_carry(cn,in2,0)) { destroy_item(in2); return; } if (ch[cn].flags&CF_PLAYER) dlog(cn,in2,"took from ice itemspawn"); ch[cn].citem=in2; ch[cn].flags|=CF_ITEMS; it[in2].carried=cn; log_char(cn,LOG_SYSTEM,0,"You got a %s.",it[in2].name); }
int do_take(int cn,int dir) { int m,x,y,in; if (cn<1 || cn>=MAXCHARS) { error=ERR_ILLEGAL_CHARNO; return 0; } if (ch[cn].flags&(CF_DEAD)) { error=ERR_DEAD; return 0; } if (!dx2offset(dir,&x,&y,NULL)) { error=ERR_ILLEGAL_DIR; return 0; } if (ch[cn].citem) { error=ERR_HAVE_CITEM; return 0; } x+=ch[cn].x; y+=ch[cn].y; if (x<1 || x>MAXMAP-2 || y<1 || y>MAXMAP-2) { error=ERR_ILLEGAL_COORDS; return 0; } m=x+y*MAXMAP; if (!(in=map[m].it)) { error=ERR_NO_ITEM; return 0; } if (in<1 || in>=MAXITEM) { elog("do_take(): item number on map position %d,%d is out of bounds.",x,y); map[m].it=0; error=ERR_CONFUSED; return 0; } if (!(it[in].flags&IF_TAKE)) { error=ERR_NOT_TAKEABLE; return 0; } if (!can_carry(cn,in,0)) { error=ERR_NOT_TAKEABLE; return 0; } ch[cn].action=AC_TAKE; ch[cn].act1=in; ch[cn].duration=speed(ch[cn].value[0][V_SPEED],ch[cn].speed_mode,DUR_MISC_ACTION); if (ch[cn].speed_mode==SM_FAST) ch[cn].endurance-=end_cost(cn); ch[cn].dir=dir; return 1; }
void cmd_steal(int cn) { int co,x,y,n,cnt,in=0,chance,dice,diff,m; if (!ch[cn].prof[P_THIEF]) { log_char(cn,LOG_SYSTEM,0,"You are not a thief, you cannot steal."); return; } if (ch[cn].action!=AC_IDLE) { log_char(cn,LOG_SYSTEM,0,"You can only steal when standing still."); return; } if (ch[cn].citem) { log_char(cn,LOG_SYSTEM,0,"Please free your hand (mouse cursor) first."); return; } dx2offset(ch[cn].dir,&x,&y,NULL); x+=ch[cn].x; y+=ch[cn].y; if (x<1 || x>=MAXMAP-1 || y<1 || y>=MAXMAP-1) { log_char(cn,LOG_SYSTEM,0,"Out of map."); return; } m=x+y*MAXMAP; co=map[m].ch; if (!co) { log_char(cn,LOG_SYSTEM,0,"There's no one to steal from."); return; } if (!can_attack(cn,co)) { log_char(cn,LOG_SYSTEM,0,"You cannot steal from someone you are not allowed to attack."); return; } if (map[m].flags&(MF_ARENA|MF_CLAN)) { log_char(cn,LOG_SYSTEM,0,"You cannot steal inside an arena."); return; } if (!(ch[co].flags&CF_PLAYER)) { log_char(cn,LOG_SYSTEM,0,"You can only steal from players."); return; } if (ch[co].driver==CDR_LOSTCON) { log_char(cn,LOG_SYSTEM,0,"You cannot steal from lagging players."); return; } if (areaID==20) { log_char(cn,LOG_SYSTEM,0,"You cannot steal in Live Quests."); return; } if (ch[co].action!=AC_IDLE || ticker-ch[co].regen_ticker<TICKS) { log_char(cn,LOG_SYSTEM,0,"You cannot steal from someone if your victim is not standing still."); return; } for (n=cnt=0; n<INVENTORYSIZE; n++) { if (n>=12 && n<30) continue; if ((in=ch[co].item[n]) && !(it[in].flags&IF_QUEST) && can_carry(cn,in,1)) cnt++; } if (!cnt) { log_char(cn,LOG_SYSTEM,0,"You could not find anything to steal."); return; } cnt=RANDOM(cnt); for (n=cnt=0; n<INVENTORYSIZE; n++) { if (n>=12 && n<30) continue; if ((in=ch[co].item[n]) && !(it[in].flags&IF_QUEST) && can_carry(cn,in,1)) { if (cnt<1) break; cnt--; } } if (n==INVENTORYSIZE) { log_char(cn,LOG_SYSTEM,0,"You could not find anything to steal (2)."); return; } diff=(ch[cn].value[0][V_STEALTH]-ch[co].value[0][V_PERCEPT])/2; chance=40+diff; if (chance<10) { log_char(cn,LOG_SYSTEM,0,"You'd get caught for sure. You decide not to try."); return; } chance=min(chance,ch[cn].prof[P_THIEF]*3); dice=RANDOM(100); diff=chance-dice; if (diff<-20) { log_char(cn,LOG_SYSTEM,0,"%s noticed your attempt and stopped you from stealing.",ch[co].name); ch[cn].endurance=1; if (ch[co].flags&CF_PLAYER) { log_char(co,LOG_SYSTEM,0,"°c3%s tried to steal from you!",ch[cn].name); } else notify_char(co,NT_GOTHIT,cn,0,0); return; } dlog(co,in,"dropped because %s stole it",ch[cn].name); remove_item_char(in); if (!give_char_item(cn,in)) { destroy_item(in); elog("had to destroy item in cmd_steal()!"); return; } add_pk_steal(cn); if (diff<0) { log_char(cn,LOG_SYSTEM,0,"%s noticed your theft, but you managed to steal a %s anyway.",ch[co].name,it[in].name); ch[cn].endurance=1; if (ch[co].flags&CF_PLAYER) { log_char(co,LOG_SYSTEM,0,"°c3%s stole your %s!",ch[cn].name,it[in].name); } else notify_char(co,NT_GOTHIT,cn,0,0); } else log_char(cn,LOG_SYSTEM,0,"You stole a %s without %s noticing.",it[in].name,ch[co].name); }
/* Returns 1 when something was stolen (or at least, when N should flee now) * Returns -1 if the monster died in the attempt * Avoid stealing the object stealoid */ int steal(struct monst *mtmp, char *objnambuf) { struct obj *otmp; int tmp, could_petrify, named = 0, armordelay; boolean monkey_business; /* true iff an animal is doing the thievery */ if (objnambuf) *objnambuf = '\0'; /* the following is true if successful on first of two attacks. */ if (!monnear(mtmp, u.ux, u.uy)) return 0; /* food being eaten might already be used up but will not have been removed from inventory yet; we don't want to steal that, so this will cause it to be removed now */ if (occupation) maybe_finished_meal(FALSE); if (!invent || (inv_cnt() == 1 && uskin)) { nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); else pline("%s tries to rob you, but there is nothing to steal!", Monnam(mtmp)); return 1; /* let her flee */ } /* Monkey or mugger robbing you. You don't wanna be charmed/seduced by a mugger. */ monkey_business = is_robber(mtmp->data); if (monkey_business) { ; /* skip ring special cases */ } else if (Adornment & LEFT_RING) { otmp = uleft; goto gotobj; } else if (Adornment & RIGHT_RING) { otmp = uright; goto gotobj; } tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); if (!tmp) goto nothing_to_steal; tmp = rn2(tmp); for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) break; if (!otmp) { warning("Steal fails!"); return 0; } /* can't steal gloves while wielding - so steal the wielded item. */ if (otmp == uarmg && uwep) otmp = uwep; /* can't steal armor while wearing cloak - so steal the cloak. */ else if (otmp == uarm && uarmc) otmp = uarmc; else if (otmp == uarmu && uarmc) otmp = uarmc; else if (otmp == uarmu && uarm) otmp = uarm; gotobj: if (otmp->o_id == stealoid) return 0; /* animals can't overcome curse stickiness nor unlock chains */ if (monkey_business) { boolean ostuck; /* is the player prevented from voluntarily giving up this item? (ignores loadstones; the !can_carry() check will catch those) */ if (otmp == uball) ostuck = TRUE; /* effectively worn; curse is implicit */ else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) ostuck = FALSE; /* not really worn; curse doesn't matter */ else ostuck = (otmp->cursed && otmp->owornmask); if (ostuck || !can_carry(mtmp, otmp)) { static const char * const how[] = { "steal","snatch","grab","take" }; cant_take: pline("%s tries to %s your %s but gives up.", Monnam(mtmp), how[rn2(SIZE(how))], (otmp->owornmask & W_ARMOR) ? equipname(otmp) : cxname(otmp)); /* the fewer items you have, the less likely the thief is going to stick around to try again (0) instead of running away (1) */ return !rn2(inv_cnt() / 5 + 2); } } if (otmp->otyp == LEASH && otmp->leashmon) { if (monkey_business && otmp->cursed) goto cant_take; o_unleash(otmp); } /* you're going to notice the theft... */ stop_occupation(); if ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ switch(otmp->oclass) { case TOOL_CLASS: case AMULET_CLASS: case RING_CLASS: case FOOD_CLASS: /* meat ring */ remove_worn_item(otmp, TRUE); break; case ARMOR_CLASS: armordelay = objects[otmp->otyp].oc_delay; /* Stop putting on armor which has been stolen. */ if (donning(otmp)) { remove_worn_item(otmp, TRUE); break; } else if (monkey_business) { /* animals usually don't have enough patience to take off items which require extra time */ if (armordelay >= 1 && rn2(10)) goto cant_take; remove_worn_item(otmp, TRUE); break; } else { int curssv = otmp->cursed; int slowly; boolean seen = canspotmon(level, mtmp); otmp->cursed = 0; /* can't charm you without first waking you */ if (multi < 0 && is_fainted()) unmul(NULL); slowly = (armordelay >= 1 || multi < 0); if (flags.female) pline("%s charms you. You gladly %s your %s.", !seen ? "She" : Monnam(mtmp), curssv ? "let her take" : slowly ? "start removing" : "hand over", equipname(otmp)); else pline("%s seduces you and %s off your %s.", !seen ? "She" : Adjmonnam(mtmp, "beautiful"), curssv ? "helps you to take" : slowly ? "you start taking" : "you take", equipname(otmp)); named++; /* the following is to set multi for later on */ nomul(-armordelay, "taking off clothes"); remove_worn_item(otmp, TRUE); otmp->cursed = curssv; if (multi < 0){ /* multi = 0; nomovemsg = 0; afternmv = 0; */ stealoid = otmp->o_id; stealmid = mtmp->m_id; afternmv = stealarm; return 0; } } break; default: warning("Tried to steal a strange worn thing. [%d]", otmp->oclass); } } else if (otmp->owornmask) remove_worn_item(otmp, TRUE); /* do this before removing it from inventory */ if (objnambuf) strcpy(objnambuf, yname(otmp)); /* set mavenge bit so knights won't suffer an * alignment penalty during retaliation; */ mtmp->mavenge = 1; freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])); mpickobj(mtmp,otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { minstapetrify(mtmp, TRUE); return -1; } return (multi < 0) ? 0 : 1; }
/* Returns 1 when something was stolen (or at least, when N should flee now) * Returns -1 if the monster died in the attempt * Avoid stealing the object stealoid */ int steal(struct monst *mtmp, const char **objnambuf) { struct obj *otmp; int tmp, could_petrify, named = 0, armordelay, slowly = 0; boolean monkey_business; /* true iff an animal is doing the thievery */ if (objnambuf) *objnambuf = ""; /* the following is true if successful on first of two attacks. */ if (!monnear(mtmp, u.ux, u.uy)) return 0; if (!invent || (inv_cnt(FALSE) == 1 && uskin())) { nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); else pline("%s tries to rob you, but there is nothing to steal!", Monnam(mtmp)); return 1; /* let her flee */ } monkey_business = is_animal(mtmp->data); if (monkey_business) { ; /* skip ring special cases */ } else if (Adornment & W_MASK(os_ringl)) { otmp = uleft; goto gotobj; } else if (Adornment & W_MASK(os_ringr)) { otmp = uright; goto gotobj; } tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin() #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) tmp += ((otmp->owornmask & W_WORN) ? 5 : 1); if (!tmp) goto nothing_to_steal; tmp = rn2(tmp); for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin() #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) if ((tmp -= ((otmp->owornmask & W_WORN) ? 5 : 1)) < 0) break; if (!otmp) { impossible("Steal fails!"); return 0; } /* can't steal gloves while wielding - so steal the wielded item. */ if (otmp == uarmg && uwep) otmp = uwep; /* can't steal armor while wearing cloak - so steal the cloak. */ else if (otmp == uarm && uarmc) otmp = uarmc; else if (otmp == uarmu && uarmc) otmp = uarmc; else if (otmp == uarmu && uarm && !uskin()) otmp = uarm; gotobj: /* animals can't overcome curse stickiness nor unlock chains */ if (monkey_business) { boolean ostuck; /* is the player prevented from voluntarily giving up this item? (ignores loadstones; the !can_carry() check will catch those) */ if (otmp == uball) ostuck = TRUE; /* effectively worn; curse is implicit */ else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) ostuck = FALSE; /* not really worn; curse doesn't matter */ else ostuck = (otmp->cursed && otmp->owornmask); if (ostuck || !can_carry(mtmp, otmp)) { static const char *const how[] = { "steal", "snatch", "grab", "take" }; cant_take: pline("%s tries to %s your %s but gives up.", Monnam(mtmp), how[rn2(SIZE(how))], (otmp->owornmask & W_ARMOR) ? equipname(otmp) : cxname(otmp)); /* the fewer items you have, the less likely the thief is going to stick around to try again (0) instead of running away (1) */ return !rn2(inv_cnt(FALSE) / 5 + 2); } } if (otmp->otyp == LEASH && otmp->leashmon) { if (monkey_business && otmp->cursed) goto cant_take; o_unleash(otmp); } /* you're going to notice the theft... */ action_interrupted(); if (otmp->owornmask & W_WORN) { switch (otmp->oclass) { case TOOL_CLASS: case AMULET_CLASS: case RING_CLASS: case FOOD_CLASS: /* meat ring */ remove_worn_item(otmp, TRUE); break; case ARMOR_CLASS: armordelay = objects[otmp->otyp].oc_delay; if (monkey_business) { /* animals usually don't have enough patience to take off items which require extra time */ if (armordelay >= 1 && rn2(10)) goto cant_take; remove_worn_item(otmp, TRUE); break; } else { int curssv = otmp->cursed; boolean seen = canspotmon(mtmp); otmp->cursed = 0; /* can't charm you without first waking you */ cancel_helplessness(hm_fainted, "Someone revives you."); slowly = (armordelay >= 1 || u_helpless(hm_all)); if (u_helpless(hm_all)) { pline("%s tries to %s you, but is dismayed by your lack of " "response.", !seen ? "She" : Monnam(mtmp), u.ufemale ? "charm" : "seduce"); return (0); } if (u.ufemale) pline("%s charms you. You gladly %s your %s.", !seen ? "She" : Monnam(mtmp), curssv ? "let her take" : slowly ? "start removing" : "hand over", equipname(otmp)); else pline("%s seduces you and %s off your %s.", !seen ? "She" : Adjmonnam(mtmp, "beautiful"), curssv ? "helps you to take" : slowly ? "you start taking" : "you take", equipname(otmp)); named++; if (armordelay) helpless(armordelay, hr_busy, "taking off clothes", "You finish disrobing."); remove_worn_item(otmp, TRUE); otmp->cursed = curssv; /* Note: it used to be that the nymph would wait for you to disrobe, then take the item, but that lead to huge complications in the code (and a rather unfun situation where the nymph could chain armor theft), and some resulting bugs. Instead, we just go down the normal codepath; you lose the item, and you're left helpless for the length of time it should have taken to remove. The nymph will stay around (due to the slowly || u_helpless(hm_all) check at the end of the function). */ } break; default: impossible("Tried to steal a strange worn thing. [%d]", otmp->oclass); } } else if (otmp->owornmask) remove_worn_item(otmp, TRUE); /* do this before removing it from inventory */ if (objnambuf) *objnambuf = yname(otmp); /* set mavenge bit so knights won't suffer an alignment penalty during retaliation; */ mtmp->mavenge = 1; freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])); mpickobj(mtmp, otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_MASK(os_armg))) { minstapetrify(mtmp, TRUE); return -1; } return (slowly || u_helpless(hm_all)) ? 0 : 1; }