// Taniwha 1995. Odds of stealing an item, and the XP for it.
// Factors to consider. Weight loss on victim.
// Value
// Relative level and dex
// For XP calcs. Take relative level, weight and value into account
//
// Cleanup by Wonderflug
// Also redid success calcs.
#include "tweaks.h"
#define CAUGHT "caught_stealing"
#define STOLEN "stolen"
#define VMOD 1000 // XP divider on value
int steal_succeed(object me, object her,object it)
{
int base_chance, mult, chance;
int v, xp;
float ratio;
if(it->query_property("stolen"))
return 1;
if(it->query_property("nosteal"))
return 0;
if ( her->query_property("steal at will") )
return 1;
me->add_timed_property("noguild",1,1);
if ( me->query_guild_name() == "thief" )
mult = 2;
else
mult = 4/3;
base_chance = 20 + me->query_level()*mult + me->query_dex();
base_chance -= her->query_level();
if ( me->query_hide_shadow() )
base_chance += 10;
base_chance = ( base_chance > 95 ? 95 : base_chance );
// The amount that the container gets adjusted by removing the item
// should be taken into account. RELATIVE amount, not absolute.
// I use environment(it) to allow stealing from containers in the future.
ratio = it->query_weight() + 0.0;
if ( ratio > 0 )
ratio /= environment(it)->query_loc_weight();
// Smaller ratios increase chance, larger lower chance
// We allow 0.05 adjustment to be no penalty, and max penalty is
// is 75%
ratio = 1.05 - ratio;
ratio = ( ratio < 0.25 ? 0.25 : ( ratio > 1.0 ? 1.0 : ratio ));
// Minimum 10% chance always
chance = base_chance * ratio;
chance = ( chance < 10 ? 10 : chance );
if ( me->query_creator() )
write("Base base: "+base_chance+"\nRatio: "+ratio+"\n"
"Adjusted chance: "+chance+"\n");
// The roll, anticlimactic isn't it?
if ( random(100) > chance )
return 0;
// They succeeded, calculate some xp to give them.
v = it->query_value()/VMOD;
xp = (v*(100-chance));
xp += 1;
if(xp > 150)
xp = 50+random(150);
xp *= ((her->query_level() - me->query_level())/3);
if(xp <= 0)
xp = 1;
if( xp > (100* her->query_level()))
xp = 100* her->query_level();
if(me->query_creator())
write("Xp = "+xp+".\n");
return xp;
}
void fail(object me,object who, int cost);
int steal(string str,object thief)
{
object me,*vat,*hoo;
int cost, vic_lev,diff, thief_lev,xp;
int i,v;
string what, who;
mixed thwap;
if(thief)
me = thief;
else
me = this_player();
str = me->expand_nickname(str);
if (me->query_level()<=2)
{
tell_object(me,"You must be over level 2 to steal.\n");
return 1;
}
if(me->query_dead())
{
tell_object(me,"You are dead! It is not possible to steal.\n");
return 1;
}
notify_fail("Usage: steal <object> from <person/monster>.\n");
if (!str)
return 0;
if (sscanf(str,"%s from %s",what,who)!=2)
return 0;
/* Checks on me */
if( (int)me->query_property(CAUGHT) == 1 )
{
tell_object(me,"Your hands are shaking from your previous near "
"death experience.\n");
return 1;
}
if( (int)me->query_property(CAUGHT) == 2 )
{
tell_object(me,"You so embarassed by your previous failure that you "
"can't work up the courage to steal again yet.\n");
return 1;
}
/* Checks on him */
hoo=find_match(who,environment(me));
if (!sizeof(hoo))
{
tell_object(me,"I don't see a "+who+" in here.\n");
return 1;
}
if(!living(hoo[0]) || hoo[0]->query_dead())
{
tell_object(me,"It's not alive.\n");
return 1;
}
if ( hoo[0] == me )
{
tell_object(me, "You try to steal from yourself, unfortunately you're "
"so bad you get noticed.\n");
return 1;
}
if (hoo[0]->query_creator()) /* are we currently in a creator char :)*/
{
tell_object(me,"You wouldn't want to steal anything from an immortal, "
"would you?\n");
return 1;
}
if ( environment(hoo[0])->query_property("nosteal") )
{
tell_object(me,"There is a time and place for stealing, and your "
"instincts tell you this is not it.\n");
return 1;
}
if ( hoo[0]->query_property("nosteal") )
{
tell_object(me, "That one looks pretty alert right now, maybe try "
"later.\n");
return 1;
}
if( sizeof(me->query_attacker_list()) ||
(member_array(me,hoo[0]->query_attacker_list()) != -1))
{
tell_object(me,"You can't steal while fighting something.\n");
return 1;
}
/* Checks on it */
vat=find_match(what,hoo[0]);
if (!sizeof(vat))
{
tell_object(me,"Can not find "+what+" on "+capitalize(who)+".\n");
return 1;
}
if (vat[0]->query_in_use())
{
tell_object(me,"You can't steal equipment in use.\n");
return 1;
}
vic_lev=(int)hoo[0]->query_level();
thief_lev = me->query_level() + me->query_dex();
diff=vic_lev-thief_lev;
if (diff<1) diff=2;
cost = ((STEAL_COST * diff)/10)+3;
if ((int)me->query_gp() < cost)
{
tell_object(me,"You seem to be too worn out to do that.\n");
return 1;
}
// Stealing Objects, risk /XP based on weight
if ((string)vat[0]->query_name() != "coin")
{
if( !(xp = steal_succeed(me,hoo[0],vat[0])))
{
fail(me,hoo[0],cost);
return 1;
}
if ( vat[0]->move(me) )
{
tell_object(me, "Hmm, couldn't steal that for some reason.\n");
return 1;
}
tell_object(me,"You snag the "+vat[0]->short()+" from "
+hoo[0]->query_cap_name()+".\n");
vat[0]->add_property(STOLEN,1);
me->adjust_xp(xp);
me->adjust_gp(-cost);
return 1;
}
// Stealing coins
if ( !(hoo[0]->query_property("steal at will")) )
{
if(random((int)me->query_level()+(int)me->query_dex()) <
random((int)hoo[0]->query_level() + diff) )
{
fail(me,hoo[0], cost);
return 1;
}
}
/* Here is the code for stealing money, not easy to implement a good
* method for this. But the one here now doesen't work.. trying to fix it.
* Baldrick oct '94.
* Taniwha 1995, they can steal their level in coins
*/
thwap = (mixed)hoo[0]->query_money_array();
diff = random(thief_lev)+2;
if(me->query_guild_name() != "thief")
diff /= 2;
if(!sizeof(thwap))
{
tell_object(me,"Hmm he's broke, nothing but moths, oh well, "
"live and learn.\n");
me->adjust_gp(-cost);
return 1;
}
tell_object(me,"You snag ");
for(i = sizeof(thwap) -1;diff > 0 && i > 0; i -= 2)
{
v = random(diff);
if( v > thwap[i] )
v = thwap[i];
if(v)
{
me->adjust_money(v,thwap[i-1]);
tell_object(me,sprintf("%i %s, ",v,thwap[i-1]));
hoo[0]->adjust_money(-v,thwap[i-1]);
diff -= v;
}
}
tell_object(me,"coins.\n");
me->adjust_gp(-cost);
return 1;
}
void fail(object me,object who, int cost)
{
string bing, sme;
int ldiff;
bing=(string)who->query_cap_name();
sme=(string)me->query_cap_name();
tell_object(me,"Oh bugger - "+bing+
" seems to have noticed your activities.\n");
tell_object(who,"You suddenly notice "+sme+
" groping around in your pockets.\n");
tell_room(environment(me),sme+" suddenly has an embarrasing moment "
"in pocket picking. "+bing+" doesn't look too happy.\n",
({who,me}));
who->add_timed_property("nosteal",1,100);
if( !me->query_creator() ) // Taniwha, so I don't waste time testing this
{
ldiff = (int)who->query_level() - (int)me->query_level();
if (!interactive(who))
who->attack_by(me); /* mean and nasty :) */
else /* since players won't auto-attack */
{
if(ldiff > 0)
me->add_timed_property(CAUGHT,1,ldiff * CAUGHT_LOCK);
else if(ldiff < 0)
me->add_timed_property(CAUGHT,2, -(ldiff * CAUGHT_LOCK));
}
}
me->adjust_gp(- ((cost/3)+1));
}
string help()
{
return
"\n\nSyntax: steal <object> from <object>\n"
"GP cost: variable, dependent on level of victim and thief\n"
"Description:\n"
" This command lets you steal an object from another player "
"or monster. Being hidden helps, success is based on your level, "
"the victim's level, and the weight of the object you're trying to "
"steal. For the more valuable items (not including coins), you'll "
"get some xp if you're robbing a fairly worthy victim. Also note "
"the less a person has the more likely they're gonna notice something "
"missing. And lastly, thieves of course are naturally better at this "
"than anyone else.\n";
}