/*
Quest Bits for Mobprogs by Igor van den Hoven.
The Diku and Merc license apply. This code is compatible with smaug muds.
*/
/*
The idea of this snippet is to move away from the traditional if value
== (number between -2 and +2 billion) check.
Given the average quest has around 10 steps you only need 4 bits of a
32 bit integer to store it. If you have a large area and a quest value
assigned for a player for that area you can add a total of eight 10 step
quests stored in a 32 bit integer.
Using quest[MAX_VNUM / 100] is an easy way to create a quest value for
each area, and you can access it with: ch->pcdata->quest[mob->vnum / 100]
with ch being the player and mob being the mob setting the quest value.
In this code you define a bit range by giving the first bit, next
giving the number of bits, followed by the value you want those bits
to hold. 4 bits would give a value between 0 and 15, 8 bits a value
between 0 and 255 (which should be enough for everyone).
To set a quest value you'd use: mpmset $n quest 0 4 1. 0 would be the
first bit, 4 would be the total number of bits, and 1 is the value to
assign to them. To check if bit 1 to 4 has the value 1 you'd use:
if quest (0,4,$n) == 1.
When adding another quest you'd start out with: if quest (4,4,$n) == 0
to see if the player has or hasn't started the quest assigned to bit
5 to 8.
Methods for saving and reading aren't included, this is pretty much
a proof of concept.
*/
// In mud_prog.c add these two functions:
int get_quest_value(int quest, int fBit, int nBit)
{
int cnt, value = 0;
for (cnt = fBit ; cnt < fBit + nBit ; cnt++)
{
if (IS_SET(quest, 1 << cnt))
{
SET_BIT(value, 1 << (cnt - fBit));
}
}
return value;
}
void set_quest_value(int *quest, int fBit, int nBit, int value)
{
int cnt;
for (cnt = fBit ; cnt < fBit + nBit ; cnt++)
{
if (IS_SET(value, 1 << (cnt - fBit)))
{
SET_BIT(*quest, 1 << cnt);
}
else
{
REMOVE_BIT(*quest, 1 << cnt);
}
}
}
// In mprog_do_ifcheck add:
if( !str_cmp( chck, "quest" ) )
{
int fBit, nBit;
char name[MAX_INPUT_LENGTH];
if (sscanf(arg, "%d,%d,%s", &fBit, &nBit, name) != 3)
{
return 0; /* error */
}
if ( name[0] == '$' )
{
switch ( name[1] )
{
case 'i':
chkchar = mob;
break;
case 'n':
chkchar = actor;
break;
case 't':
chkchar = ( CHAR_DATA * ) vo;
break;
case 'r':
chkchar = rndm;
break;
default:
return 0; /* error */
}
}
if (chkchar)
{
if (IS_NPC(chkchar)
{
lhsvl = get_quest_value(chkchar->quest, fBit, nBit);
}
else
{
lhsvl = get_quest_value(chkchar->quest[mob->in_room->area->low_r_vnum / 100], fBit, nBit);
}
rhsvl = atoi(rval);
return mprog_veval(lhsvl, opr, rhsvl);
}
else
{
return 0; /* error */
}
}
// In mpxset.c add:
if( !str_cmp( arg2, "quest" ) )
{
int fBit, nBit, value;
if (sscanf(arg3,"%d %d %d", &fBit, &nBit, &value) != 3)
{
return;
}
if (IS_NPC(victim)
{
set_quest_value(&victim->quest, fBit, nBit, value);
}
else
{
set_quest_value(&victim->quest[ch->in_room->area->low_r_vnum / 100], fBit, nBit, value);
}
return;
}
// In mud.h add to char_data:
int quest;
// And to player_data;
int quest[MAX_VNUM/100];