/****************************************************************************
* [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// *
* -----------------------------------------------------------| (0...0) *
* SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( *
* -----------------------------------------------------------| {o o} *
* SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ *
* Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~*
* Tricops and Fireblade | *
* ------------------------------------------------------------------------ *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* ------------------------------------------------------------------------ *
* Main structure manipulation module *
****************************************************************************/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "mud.h"
extern int top_exit;
extern int top_ed;
extern int top_affect;
extern int cur_qobjs;
extern int cur_qchars;
extern CHAR_DATA *gch_prev;
extern OBJ_DATA *gobj_prev;
CHAR_DATA *cur_char;
ROOM_INDEX_DATA *cur_room;
bool cur_char_died;
ch_ret global_retcode;
int saving_mount_on_quit;
int cur_obj;
int cur_obj_serial;
int top_map_mob;
bool cur_obj_extracted;
obj_ret global_objcode;
OBJ_DATA *group_object(OBJ_DATA * obj1, OBJ_DATA * obj2);
bool in_magic_container(OBJ_DATA * obj);
/* Strlen_color by Rusty, useful for skipping over colors */
int strlen_color(char *argument)
{
char *str;
int i, length;
str = argument;
if (argument == NULL)
return 0;
for (length = i = 0; i < strlen(argument); ++i)
{
if ((str[i] != '&') && (str[i] != '^'))
++length;
if ((str[i] == '&') || (str[i] == '^'))
{
if ((str[i] == '&') && (str[i + 1] == '&'))
length = 2 + length;
else if ((str[i] == '^') && (str[i + 1] == '^'))
length = 2 + length;
else
--length;
}
}
return length;
}
/*
* Retrieve a character's trusted level for permission checking.
*/
sh_int get_trust(CHAR_DATA * ch)
{
if (IS_NPC(ch))
return LEVEL_PC;
if (ch->desc && ch->desc->original)
ch = ch->desc->original;
if (ch->trust != 0)
return ch->trust;
if (ch->level >= LEVEL_IMMORTAL && IS_RETIRED(ch)) /* Tracker1 */
return LEVEL_IMMORTAL; /* Tracker1 */
return ch->level;
}
/*
* New FLevel trust return, for use of the flevel attribute. - Xerves 3-12-98
*/
sh_int get_ftrust(CHAR_DATA * ch)
{
if (ch->desc && ch->desc->original)
ch = ch->desc->original;
if (IS_NPC(ch))
return ch->level;
if (IS_RETIRED(ch))
return LEVEL_IMMORTAL; /* Tracker1 */
if (ch->level > ch->pcdata->flevel)
return ch->level;
return ch->pcdata->flevel;
}
/*
* Retrieve a character's age.
*/
sh_int get_age(CHAR_DATA * ch)
{
if (IS_NPC(ch))
return 17;
return 17 + (ch->played + (current_time - ch->pcdata->logon)) / 72000;
}
/*
* Retrieve character's current strength.
*/
sh_int get_curr_str(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_str + URANGE(-4, ch->mod_str, 4), max);
}
/*
* Retrieve character's current intelligence.
*/
sh_int get_curr_int(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_int + URANGE(-4, ch->mod_int, 4), max);
}
/*
* Retrieve character's current wisdom.
*/
sh_int get_curr_wis(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_wis + URANGE(-4, ch->mod_wis, 4), max);
}
/*
* Retrieve character's current dexterity.
*/
sh_int get_curr_dex(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_dex + URANGE(-4, ch->mod_dex, 4), max);
}
/*
* Retrieve character's current constitution.
*/
sh_int get_curr_con(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_con + URANGE(-4, ch->mod_con, 4), max);
}
/*
* Retrieve character's current charisma.
*/
sh_int get_curr_cha(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_cha + URANGE(-4, ch->mod_cha, 4), max);
}
/*
* Retrieve character's current luck.
*/
sh_int get_curr_lck(CHAR_DATA * ch)
{
sh_int max;
max = 25;
return URANGE(3, ch->perm_lck + URANGE(-4, ch->mod_lck, 4), max);
}
sh_int get_curr_agi(CHAR_DATA * ch)
{
sh_int max;
max = 100;
return URANGE(10, ch->perm_agi + URANGE(-15, ch->mod_agi, 15), max);
}
/* Below 2 functions are used to return points and masteries of spells. Mainly to
compute an estimated value for mobs -- Xerves 2/00 */
sh_int get_mastered_value(CHAR_DATA *ch, int sn)
{
if (!IS_NPC(ch))
{
return URANGE(0, ch->pcdata->ranking[sn], MAX_RANKING);
}
else
{
if (ch->max_hit <= 28)
return get_mastery_value(ch, sn, 0, SPOWER_MIN);
else if (ch->max_hit <= 77)
return get_mastery_value(ch, sn, 0, SPOWER_LOW);
else if (ch->max_hit <= 200)
return get_mastery_value(ch, sn, 0, SPOWER_MED);
else if (ch->max_hit <= 694)
return get_mastery_value(ch, sn, 0, SPOWER_HI);
else if (ch->max_hit <= 1022)
return get_mastery_value(ch, sn, 0, SPOWER_GREAT);
else if (ch->max_hit <= 3000)
return get_mastery_value(ch, sn, 0, SPOWER_GREATER);
else
return get_mastery_value(ch, sn, 0, SPOWER_GREATEST);
}
}
sh_int get_learned_value(CHAR_DATA *ch, int sn)
{
if (!IS_NPC(ch))
{
return URANGE(0, ch->pcdata->learned[sn], MAX_SKPOINTS);
}
else
{
if (ch->max_hit <= 28)
return get_point_value(ch, sn, 0, SPOWER_MIN);
else if (ch->max_hit <= 77)
return get_point_value(ch, sn, 0, SPOWER_LOW);
else if (ch->max_hit <= 200)
return get_point_value(ch, sn, 0, SPOWER_MED);
else if (ch->max_hit <= 694)
return get_point_value(ch, sn, 0, SPOWER_HI);
else if (ch->max_hit <= 1022)
return get_point_value(ch, sn, 0, SPOWER_GREAT);
else if (ch->max_hit <= 3000)
return get_point_value(ch, sn, 0, SPOWER_GREATER);
else
return get_point_value(ch, sn, 0, SPOWER_GREATEST);
}
}
/* Below 2 functions are used to return points and masteries of spells. Mainly to
compute an estimated value for mobs -- Xerves 2/00 */
sh_int get_point_value(CHAR_DATA * ch, int sn, int isobj, int lv)
{
if (!IS_NPC(ch) && isobj == 0 && ch->pcdata->learned[sn] > 1)
return ch->pcdata->learned[sn];
else if (lv >= SPOWER_MIN)
{
if (lv == SPOWER_MIN)
return number_range(1, 2);
if (lv == SPOWER_LOW)
return number_range(2, 4);
if (lv == SPOWER_MED)
return number_range(3, 6);
if (lv == SPOWER_HI)
return number_range(5, 8);
if (lv == SPOWER_GREAT)
return number_range(7, 10);
if (lv == SPOWER_GREATER)
return number_range(8, 12);
if (lv == SPOWER_GREATEST)
return number_range(10, 14);
}
else if (IS_NPC(ch) && isobj == 0)
{
if (ch->max_hit <= 28)
return get_point_value(ch, sn, 0, SPOWER_MIN);
else if (ch->max_hit <= 77)
return get_point_value(ch, sn, 0, SPOWER_LOW);
else if (ch->max_hit <= 200)
return get_point_value(ch, sn, 0, SPOWER_MED);
else if (ch->max_hit <= 694)
return get_point_value(ch, sn, 0, SPOWER_HI);
else if (ch->max_hit <= 1022)
return get_point_value(ch, sn, 0, SPOWER_GREAT);
else if (ch->max_hit <= 3000)
return get_point_value(ch, sn, 0, SPOWER_GREATER);
else
return get_point_value(ch, sn, 0, SPOWER_GREATEST);
}
return 1;
}
sh_int get_mastery_value(CHAR_DATA * ch, int sn, int isobj, int lv)
{
int di;
if (!IS_NPC(ch) && isobj == 0 && ch->pcdata->ranking[sn] > 1)
return ch->pcdata->ranking[sn];
else if (lv >= SPOWER_MIN)
{
//mob or obj
di = dice(1, 20);
if (lv == SPOWER_MIN)
return 1;
if (lv == SPOWER_LOW)
{
if (di >= 15)
return 2;
else
return 1;
}
if (lv == SPOWER_MED)
{
if (di >= 14)
return 2;
else
return 1;
}
if (lv == SPOWER_HI)
{
if (di >= 12)
return 3;
else
return 2;
}
if (lv == SPOWER_GREAT)
{
if (di >= 4)
return 4;
else
return 3;
}
if (lv == SPOWER_GREATER)
{
if (di <= 15)
return 4;
else
return 5;
}
if (lv == SPOWER_GREATEST)
{
if (di <= 5)
return 4;
else if (di >= 16)
return 6;
else
return 5;
}
}
else if (IS_NPC(ch) && isobj == 0)
{
if (ch->max_hit <= 28)
return get_mastery_value(ch, sn, 0, SPOWER_MIN);
else if (ch->max_hit <= 77)
return get_mastery_value(ch, sn, 0, SPOWER_LOW);
else if (ch->max_hit <= 200)
return get_mastery_value(ch, sn, 0, SPOWER_MED);
else if (ch->max_hit <= 694)
return get_mastery_value(ch, sn, 0, SPOWER_HI);
else if (ch->max_hit <= 1022)
return get_mastery_value(ch, sn, 0, SPOWER_GREAT);
else if (ch->max_hit <= 3000)
return get_mastery_value(ch, sn, 0, SPOWER_GREATER);
else
return get_mastery_value(ch, sn, 0, SPOWER_GREATEST);
}
return 1;
}
/* Below 6 handler functions are used in information obtaining in the new skill system.
There are other functions in act_info.c and in mud_comm.c -- Xerves 2/00 */
// Retreives a Mastery name from its Number.
char *get_mastery_name(int mastery)
{
switch (mastery)
{
default:
return "Unknown";
case 1:
return "Beginner";
case 2:
return "Novice";
case 3:
return "Expert";
case 4:
return "Master";
case 5:
return "Elite";
case 6:
return "Flawless";
}
}
char *get_tier_name(int mastery)
{
switch (mastery)
{
default:
return "Unknown";
case 1:
return "Tier 1";
case 2:
return "Tier 2";
case 3:
return "Tier 3";
case 4:
return "Tier 4";
}
}
char *get_wplevel(int power)
{
switch (power)
{
default:
return "None";
case SPOWER_MIN:
return "Minimum";
case SPOWER_LOW:
return "Low";
case SPOWER_MED:
return "Medium";
case SPOWER_HI:
return "High";
case SPOWER_GREAT:
return "Great";
case SPOWER_GREATER:
return "Greater";
case SPOWER_GREATEST:
return "Greatest";
}
}
char *get_sphere_name2(int sphere)
{
switch(sphere)
{
default:
return "Unknown";
case 1:
return "Combat";
case 2:
return "Agent";
case 3:
return "Wizardry";
case 4:
return "Divine";
case 5:
return "Spiritual";
}
}
char *get_sphere_name(int sphere)
{
switch(sphere)
{
default:
return " Unknown ";
case 1:
return " Combat ";
case 2:
return " Agent ";
case 3:
return " Wizardry ";
case 4:
return " Divine ";
case 5:
return " Spiritual ";
}
}
/*
* Retreives a Group name from its Number. -- Xerves 1/00
*/
char *get_group_name(int group)
{
switch (group)
{
default:
return "Unknown";
case 1:
return "Air";
case 2:
return "Earth";
case 3:
return "Energy";
case 4:
return "Fire";
case 5:
return "Water";
case 6:
return "Divine";
case 7:
return "Strikes";
case 8:
return "Body";
case 9:
return "Mind";
case 10:
return "-------";
case 11:
return "Survival";
case 12:
return "Stealth";
case 13:
return "Thieving";
case 14:
return "Battle Skills";
case 15:
return "-------";
case 16:
return "Tactical";
case 17:
return "Styles";
case 18:
return "-------";
}
}
/*
* Retreives a Group name from its Number. Should be used in do_skills only since it
* includes extra values to break up Fire for Cleric and Fire for Mage
*/
char *get_group_name2(int group)
{
switch (group)
{
default:
return "Unknown";
case 1:
return "Air";
case 2:
return "Earth";
case 3:
return "Energy";
case 4:
return "Fire";
case 5:
return "Water";
case 6:
return "Divine";
case 7:
return "Strikes";
case 8:
return "Body";
case 9:
return "Mind";
case 10:
return "-------";
case 11:
return "Survival";
case 12:
return "Stealth";
case 13:
return "Thieving";
case 14:
return "Battle Skills";
case 15:
return "--------";
case 16:
return "Tactical";
case 17:
return "Styles";
case 18:
return "-------";
case 19:
return "Air";
case 20:
return "Earth";
case 21:
return "Energy";
case 22:
return "Fire";
case 23:
return "Water";
}
}
//Used in do_skills to determine percents
int is_part_sphere(int sphere, int group)
{
if (sphere == 1) //Warrior
if (group == 14 || group == 16 || group == 17)
return 1;
if (sphere == 2) //Thief
if (group == 11 || group == 12 || group == 13)
return 1;
if (sphere == 3) //Mage
if (group == 1 || group == 2 || group == 3 || group == 4 || group == 5)
return 1;
if (sphere == 4) //Cleric
if (group == 6 || group == 19 || group == 20 || group == 21 || group == 22 || group == 23)
return 1;
if (sphere == 5) //Hand to Hand
if (group == 7 || group == 8 || group == 9)
return 1;
return 0;
}
// Returns Mastery number for the name
int get_mastery_num(char *mastery)
{
char buf[MSL];
sprintf(buf, mastery);
buf[0] = UPPER(buf[0]);
if (!str_cmp(buf, "Beginner"))
return 1;
if (!str_cmp(buf, "Novice") || !str_prefix(buf, "Apprentice"))
return 2;
if (!str_cmp(buf, "Expert"))
return 3;
if (!str_cmp(buf, "Master"))
return 4;
if (!str_cmp(buf, "Elite"))
return 5;
if (!str_cmp(buf, "Flawless"))
return 6;
return -1;
}
// Get sphere number from sphere name -- Xerves 7/04
sh_int issphere(char *argument)
{
sh_int sphere = -1;
if (!str_cmp(argument, "Combat"))
sphere = 1;
if (!str_cmp(argument, "Agent"))
sphere = 2;
if (!str_cmp(argument, "Wizardry"))
sphere = 3;
if (!str_cmp(argument, "Divine"))
sphere = 4;
if (!str_cmp(argument, "Spiritual"))
sphere = 5;
return sphere;
}
/* Get group number from group name -- Xerves 1/00 */
sh_int isgroup(char *argument)
{
sh_int group = -1;
if (!str_cmp(argument, "Air"))
group = 1;
if (!str_cmp(argument, "Earth"))
group = 2;
if (!str_cmp(argument, "Energy"))
group = 3;
if (!str_cmp(argument, "Fire"))
group = 4;
if (!str_cmp(argument, "Water"))
group = 5;
if (!str_cmp(argument, "Divine"))
group = 6;
if (!str_cmp(argument, "Strikes"))
group = 7;
if (!str_cmp(argument, "Body"))
group = 8;
if (!str_cmp(argument, "Mind"))
group = 9;
if (!str_cmp(argument, "-------"))
group = 10;
if (!str_cmp(argument, "Survival"))
group = 11;
if (!str_cmp(argument, "Stealth"))
group = 12;
if (!str_cmp(argument, "Thieving"))
group = 13;
if (!str_cmp(argument, "Battle Skills"))
group = 14;
if (!str_cmp(argument, "--------"))
group = 15;
if (!str_cmp(argument, "Tactical"))
group = 16;
if (!str_cmp(argument, "Styles"))
group = 17;
if (!str_cmp(argument, "-------"))
group = 18;
return group;
}
//Movement lag, more lag the more tired you get (adding in later running, etc)
int movement_lag(CHAR_DATA *ch, int beats)
{
int percent;
int level;
if (beats < 0)
beats = 1;
percent = ch->move * 100 / 1000;
if (IS_NPC(ch) || LEARNED(ch, gsn_shadowfoot) >= 1)
{
if (percent >= 70)
beats = 1;
else if (percent >= 60)
beats = beats * 3 / 10;
else if (percent >= 50)
beats = beats * 5 / 10;
else if (percent >= 40)
beats = beats * 8 / 10;
else if (percent >= 30)
beats = beats * 11 / 10;
else if (percent >= 15)
beats = beats * 15 / 10;
else if (percent < 15)
beats = beats * 20 / 10;
}
else
{
if (percent >= 80)
beats = 1;
else if (percent >= 70)
beats = beats * 5 / 10;
else if (percent >= 60)
beats = beats * 8 / 10;
else if (percent >= 50)
beats = beats * 12 / 10;
else if (percent >= 40)
beats = beats * 15 / 10;
else if (percent >= 15)
beats = beats * 20 / 10;
else if (percent < 15)
beats = beats * 30 / 10;
}
level = POINT_LEVEL(LEARNED(ch, gsn_featherfoot), MASTERED(ch, gsn_featherfoot));
if (level > 0 && !IS_NPC(ch))
{
beats = beats * (100-(level/2)) / 100;
}
if (beats < 1)
beats = 1;
if (!IS_NPC(ch) && LEARNED(ch, gsn_featherfoot) >= 1)
learn_from_success(ch, gsn_featherfoot, NULL);
if (!IS_NPC(ch) && LEARNED(ch, gsn_featherback) >= 1)
learn_from_success(ch, gsn_featherback, NULL);
return UMIN(20, beats); //5 seconds max, anything over is just evil
}
void update_movement_points(CHAR_DATA *ch, int move)
{
int mv;
if (IS_NPC(ch))
{
if (!xIS_SET(ch->act, ACT_MOUNTSAVE))
return;
}
if (!IS_NPC(ch))
{
mv = number_range(move*.15, move*.3);
if (sysdata.stat_gain <= 3)
mv = number_range(move*.25, move*.5);
else if (sysdata.stat_gain >= 5)
mv = number_range(move*.4, move*.8);
if (ch->mover >= 35 && ch->mover < 45)
mv *= .8;
else if (ch->mover < 55)
mv *= .6;
else if (ch->mover < 65)
mv *= .5;
else if (ch->mover <= 74)
mv *= .3;
else if (ch->mover < 94)
mv *= .25;
else
mv *= .2;
if (mv == 0)
mv = 1;
if (ch->mover >= (74+get_talent_increase(ch, 8)) && ch->pcdata->per_move >= 300)
mv = 0;
ch->pcdata->per_move += mv;
if (ch->pcdata->per_move > 1000)
{
ch->mover++;
send_to_char("&C*****************************************\n\r", ch);
send_to_char("&C******You Gain 1 Point in Endurance******\n\r", ch);
send_to_char("&C*****************************************\n\r", ch);
ch->pcdata->per_move = 0;
}
if (ch->pcdata->per_move < 0)
{
ch->mover--;
send_to_char("&c*****************************************\n\r", ch);
send_to_char("&c******You Lose 1 Point in Endurance******\n\r", ch);
send_to_char("&c*****************************************\n\r", ch);
ch->pcdata->per_move = 999;
}
}
else
{
mv = number_range(move*.1, move*.25);
if (sysdata.stat_gain <= 3)
mv = number_range(move*.2, move*.4);
else if (sysdata.stat_gain >= 5)
mv = number_range(move*.35, move*.7);
if (ch->mover >= 65 && ch->mover < 75)
mv *= .7;
else if (ch->mover < 85)
mv *= .5;
else if (ch->mover < 95)
mv *= .3;
else if (ch->mover < 105)
mv *= .2;
else if (ch->mover < 115)
mv *= .15;
else if (ch->mover < 125)
mv *= .1;
else if (ch->mover < 135)
mv *= .07;
if (mv == 0)
mv = 1;
if (ch->mover == 135 && ch->m1 >= 300)
mv = 0;
ch->m1 += mv;
if (ch->m1 > 1000)
{
ch->mover++;
send_to_char("&C*************************************************\n\r", ch);
send_to_char("&C******Your Mount Gains 1 Point in Endurance******\n\r", ch);
send_to_char("&C*************************************************\n\r", ch);
ch->m1 = 0;
}
}
}
void str_load_increase(CHAR_DATA *ch, int load)
{
int mstr = 0;
int str = ch->perm_str;
int bstr;
if (load >= 51 && load <= 55)
mstr += number_range(0, 2);
else if (load >= 56 && load <= 60)
mstr += number_range(1, 2);
else if (load >= 61 && load <= 65)
mstr += number_range(2, 3);
else if (load >= 66 && load <= 70)
mstr += number_range(2, 4);
else if (load >= 71 && load <= 75)
mstr += number_range(3, 4);
else if (load >= 76 && load <= 80)
mstr += number_range(3, 5);
else if (load >= 81 && load <= 85)
mstr += number_range(4, 5);
else if (load >= 86 && load <= 90)
mstr += number_range(4, 6);
else if (load >= 91 && load <= 96)
mstr += number_range(5, 6);
else
mstr += number_range(6, 7);
if (sysdata.stat_gain <= 3)
mstr = number_range(150*mstr/100, 180*mstr/100);
else if (sysdata.stat_gain >= 5)
mstr = number_range(250*mstr/100, 300*mstr/100);
bstr = 14 + race_table[ch->race]->str_plus;
if (str == bstr - 4)
mstr *= 2;
if (str == bstr - 3)
mstr *= 1.7;
if (str == bstr - 2)
mstr *= 1.5;
if (str == bstr - 1)
mstr *= 1.2;
if (str == bstr)
mstr *= 1;
if (str == bstr + 1)
mstr *= .85;
if (str == bstr + 2)
mstr *= .7;
if (str == bstr + 3)
mstr *= .6;
if (str == bstr + 4)
mstr *= .4;
if (str == bstr + 5)
mstr *= .3;
if (str > bstr + 5) //Base + 5 should be the max unless you screwed it up
mstr = 0;
else
{
if (mstr == 0)
mstr = 1;
}
if (ch->perm_str == (14 + race_table[ch->race]->str_plus + race_table[ch->race]->str_range) && ch->pcdata->per_str >= 3000)
mstr = 0;
ch->pcdata->per_str += mstr;
if (ch->pcdata->per_str > 10000)
{
ch->perm_str++;
send_to_char("&R**************************************\n\r", ch);
send_to_char("&R*****You Gain 1 Point of Strength*****\n\r", ch);
send_to_char("&R**************************************\n\r", ch);
ch->pcdata->per_str = 0;
}
}
int calculate_movement_cost(int move, CHAR_DATA *ch)
{
int load;
int weight;
int level;
int addmove = 0;
if (ch->con_lleg <= -1)
addmove += UMAX(1, number_range(move*1.5, move*2.3));
else if (ch->con_lleg <= 10)
addmove += UMAX(1, number_range(move*1.3, move*1.5));
else if (ch->con_lleg <= 30)
addmove += UMAX(1, number_range(move*1.15, move*1.3));
else if (ch->con_lleg <= 50)
addmove += UMAX(1, number_range(move*1.05, move*1.15));
if (ch->con_rleg <= -1)
addmove += UMAX(1, number_range(move*1.5, move*2.3));
else if (ch->con_rleg <= 10)
addmove += UMAX(1, number_range(move*1.3, move*1.5));
else if (ch->con_rleg <= 30)
addmove += UMAX(1, number_range(move*1.15, move*1.3));
else if (ch->con_rleg <= 50)
addmove += UMAX(1, number_range(move*1.05, move*1.15));
move+=addmove;
if ((IS_NPC(ch) && !xIS_SET(ch->act, ACT_MOUNTSAVE)) || IS_IMMORTAL(ch))
return 1; //for now
else
{
if (ch->mover < 15)
move = move * (5 - (.1 * (ch->mover-5)));
else if (ch->mover < 25)
move = move * (4 - (.1 * (ch->mover-15)));
else if (ch->mover < 35)
move = move * (3 - (.1 * (ch->mover-25)));
else if (ch->mover < 45)
move = move * (2 - (.1 * (ch->mover-35)));
else if (ch->mover < 55)
move = move * (1.3 - (.07 * (ch->mover-45)));
else if (ch->mover < 65)
move = move * (.95 - (.035 * (ch->mover-55)));
else if (ch->mover < 75)
move = move * (.8 - (.015 * (ch->mover-65)));
else if (ch->mover < 85)
move = move * (.7 - (.01 * (ch->mover-75)));
else if (ch->mover < 95)
move = move * (.6 - (.01 * (ch->mover-85)));
else if (ch->mover < 105)
move = move * (.5 - (.01 * (ch->mover-95)));
else if (ch->mover < 115)
move = move * (.4 - (.01 * (ch->mover-105)));
else if (ch->mover < 125)
move = move * (.3 - (.01 * (ch->mover-115)));
else if (ch->mover < 135)
move = move * (.2 - (.01 * (ch->mover-125)));
else if (ch->mover >= 135)
move = move * .1;
if (!IS_NPC(ch) && ch->pcdata->learned[gsn_shadowfoot] > 0)
{
level = POINT_LEVEL(GET_POINTS(ch, gsn_shadowfoot, 0, 1), GET_MASTERY(ch, gsn_shadowfoot, 0, 1));
move = move * (100 - (15+level/2)) / 100;
learn_from_success(ch, gsn_shadowfoot, NULL);
}
if (move < 1)
move = 1;
if (!IS_NPC(ch))
weight = get_ch_carry_weight(ch);
else
{
if (ch->master)
weight = get_ch_carry_weight(ch->master);
else
weight = 1;
}
load = 100 * weight / can_carry_w(ch);
if (load > 50)
{
if (!IS_NPC(ch))
str_load_increase(ch, load);
if (!IS_NPC(ch) && ch->pcdata->learned[gsn_strongfoot] > 0)
{
level = POINT_LEVEL(GET_POINTS(ch, gsn_strongfoot, 0, 1), GET_MASTERY(ch, gsn_strongfoot, 0, 1));
load = load - (level*2/5);
learn_from_success(ch, gsn_strongfoot, NULL);
}
if (load <= 50)
;
else if (load >= 51 && load <= 55)
move *= 1.1;
else if (load >= 56 && load <= 60)
move *= 1.3;
else if (load >= 61 && load <= 65)
move *= 1.5;
else if (load >= 66 && load <= 70)
move *= 1.7;
else if (load >= 71 && load <= 75)
move *= 2;
else if (load >= 76 && load <= 80)
move *= 2.3;
else if (load >= 81 && load <= 85)
move *= 2.6;
else if (load >= 86 && load <= 90)
move *= 3;
else if (load >= 91 && load <= 96)
move *= 4;
else
move *= 5;
}
}
if (ch->rider)
move *= 2;
return move;
}
/* Below are hitroll/damroll checks to get the hitroll normally plus bonuses based
on mastery */
int get_hit_roll(CHAR_DATA * ch)
{
int hitroll;
hitroll = ch->hitroll + str_app[get_curr_str(ch)].tohit + (2 - (abs(ch->mental_state) / 10));
return hitroll;
}
int get_dam_roll(CHAR_DATA * ch)
{
int damroll;
damroll = ch->damroll + ch->damplus + str_app[get_curr_str(ch)].todam;
if (ch->mental_state > 5 && ch->mental_state < 15)
damroll++;
return damroll;
}
//Defines what the room is, 1 is safe, 2 is noloot, 3 is anitem, 4 is freekill
//Default is noloot
int check_room_pk(CHAR_DATA * ch)
{
//Do the Wilderness first
//Wilderness checks, the room itself should ALWAYS be set to noloot
if (IN_WILDERNESS(ch))
{
int stx, sty, endx, endy, x, y;
if (sysdata.resetgame)
return 4;
stx = ch->coord->x - 5;
sty = ch->coord->y - 5;
endx = ch->coord->x + 5;
endy = ch->coord->y + 5;
if (stx < 1)
stx = 1;
if (sty < 1)
sty = 1;
if (endx > MAX_X)
endx = MAX_X;
if (endy > MAX_Y)
endy = MAX_Y;
for (y = sty; y < endy + 1; y += 1)
{
for (x = stx; x < endx + 1; x += 1)
{
if (map_sector[ch->map][x][y] == SECT_ROAD)
return 2;
if (map_sector[ch->map][x][y] == SECT_BRIDGE)
return 2;
if (map_sector[ch->map][x][y] == SECT_PATH)
{
if (abs(ch->coord->y - y) <= 3 && abs(ch->coord->x - x) <= 3)
return 2;
}
}
}
return 3;
}
//A safe room is a safe room no matter what.
if (xIS_SET(ch->in_room->room_flags, ROOM_TSAFE))
return 1;
if (xIS_SET(ch->in_room->room_flags, ROOM_SAFE))
return 1;
if (xIS_SET(ch->in_room->room_flags, ROOM_FREEKILL))
return 4;
if (xIS_SET(ch->in_room->room_flags, ROOM_ANITEM))
return 3;
if (xIS_SET(ch->in_room->room_flags, ROOM_NOLOOT))
return 2;
//Check areas next, room goes before area in priority
if (IS_SET(ch->in_room->area->flags, AFLAG_NOKILL))
return 1;
if (IS_SET(ch->in_room->area->flags, AFLAG_NOLOOT))
return 2;
if (IS_SET(ch->in_room->area->flags, AFLAG_ANITEM))
return 3;
if (IS_SET(ch->in_room->area->flags, AFLAG_FREEKILL))
return 4;
if (sysdata.resetgame)
return 4;
else
return 2;
}
bool in_same_room(CHAR_DATA * ch, CHAR_DATA * victim)
{
if (IN_WILDERNESS(ch))
{
if (ch->coord->x == victim->coord->x && ch->coord->y == victim->coord->y
&& ch->map == victim->map)
return TRUE;
}
else
{
if (ch->in_room == victim->in_room)
return TRUE;
}
return FALSE;
}
bool in_hellmaze(CHAR_DATA * ch)
{
return FALSE;
}
// Send out message, doesn't use a channel, don't want to spam poor players
void hunt_message(CHAR_DATA * ch, CHAR_DATA * victim, int range)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *tochar;
int message = 1;
char buf[MSL];
char buf2[MSL];
for (d = first_descriptor; d; d = d->next)
{
if (d->connected == CON_PLAYING && d->character->in_room && d->newstate != 2)
tochar = d->character;
else
continue;
if (tochar->coord->x > -1 || tochar->coord->y > -1 || tochar->map > -1)
{
if (abs(ch->coord->x - tochar->coord->x) <= range && abs(ch->coord->y - tochar->coord->y) <= range)
{
message = number_range(1, 6);
if (message == 1)
sprintf(buf, "My first target has escaped, so &R[%s&R]%s will DIE instead.", victim->name, char_color_str(AT_GOSSIP, tochar));
else if (message == 2)
sprintf(buf, "I seek more battles, and &R[%s&R]%s looks like an easy target.", victim->name, char_color_str(AT_GOSSIP, tochar));
else if (message == 3)
sprintf(buf, "&R[%s&R]%s shall die today, I will take delight in my victory.", victim->name, char_color_str(AT_GOSSIP, tochar));
else if (message == 4)
sprintf(buf, "Come here &R[%s&R]%s, I wish to introduce you to your maker.", victim->name, char_color_str(AT_GOSSIP, tochar));
else if (message == 5)
sprintf(buf, "Poor &R[%s&R]%s, today was just not a good day to step outside.", victim->name, char_color_str(AT_GOSSIP, tochar));
else
sprintf(buf, "Life shall end for &R[%s&R]%s today, how sad.", victim->name, char_color_str(AT_GOSSIP, tochar));
sprintf(buf2, "&c&w%s [&cyells&c&w] %s'%s'", ch->short_descr, char_color_str(AT_GOSSIP, tochar), buf);
act(AT_GOSSIP, buf2, ch, NULL, tochar, TO_VICT);
}
}
}
return;
}
void find_next_target(CHAR_DATA * ch)
{
CHAR_DATA *victim;
int range, num, count, npeace, ht, x;
CHAR_DATA *pvictim = NULL;
int eqlevel = 8;
if (xIS_SET(ch->miflags, KM_ATTACKN) || xIS_SET(ch->miflags, KM_ATTACKE) || xIS_SET(ch->miflags, KM_ATTACKA))
{
count = x = 0;
range = ch->m6;
if (xIS_SET(ch->miflags, KM_ATTACKN))
npeace = 1;
else if (xIS_SET(ch->miflags, KM_ATTACKE))
npeace = 0;
else
npeace = -1;
for (victim = ch->in_room->first_person; victim; victim = victim->next_in_room)
{
if (victim->coord->x > -1 || victim->coord->y > -1 || victim->map > -1)
{
if (abs(ch->coord->x - victim->coord->x) <= range && abs(ch->coord->y - victim->coord->y) <= range)
{
if (IS_NPC(victim))
ht = victim->m4;
else
ht = victim->pcdata->hometown;
if (victim->map == ch->map && victim->level < LEVEL_IMMORTAL && can_see(ch, victim) && ch->m4 != ht
&& (npeace == -1 || kingdom_table[ch->m4]->peace[ht] <= npeace) && !xIS_SET(victim->act, ACT_PACIFIST))
{
if (!get_eq_char(victim, WEAR_NECK))
{
pvictim = victim;
eqlevel = 1;
}
if (!get_eq_char(victim, WEAR_HEAD) && eqlevel > 2)
{
pvictim = victim;
eqlevel = 2;
}
if (!get_eq_char(victim, WEAR_ARM_R) && eqlevel > 3)
{
pvictim = victim;
eqlevel = 3;
}
if (!get_eq_char(victim, WEAR_ARM_L) && eqlevel > 4)
{
pvictim = victim;
eqlevel = 4;
}
if (!get_eq_char(victim, WEAR_LEG_R) && eqlevel > 5)
{
pvictim = victim;
eqlevel = 5;
}
if (!get_eq_char(victim, WEAR_LEG_L) && eqlevel > 6)
{
pvictim = victim;
eqlevel = 6;
}
if (!get_eq_char(victim, WEAR_BODY) && eqlevel > 7)
{
pvictim = victim;
eqlevel = 7;
}
if (!pvictim)
pvictim = victim;
}
}
}
}
if (!pvictim)
{
stop_hating(ch);
stop_hunting(ch);
do_yell(ch, "Lost my target, no new ones sited, standing down.");
return;
}
else
{
hunt_message(ch, pvictim, range + 1);
start_hunting(ch, pvictim);
return;
}
}
if (xIS_SET(ch->miflags, KM_ATTACKC) || xIS_SET(ch->miflags, KM_ATTACKH))
{
count = x = 0;
for (victim = ch->in_room->first_person; victim; victim = victim->next_in_room)
{
if ((xIS_SET(ch->miflags, KM_ATTACKC) && get_wear_cloak(victim)) ||
(xIS_SET(ch->miflags, KM_ATTACKH) && get_wear_hidden_cloak(victim)))
{
if (IN_SAME_ROOM(ch, victim))
{
if (IS_NPC(victim))
ht = victim->m4;
else
ht = victim->pcdata->hometown;
if (can_see_map(ch, victim) && !is_safe(ch, victim) && ch->m4 != ht && !IS_IMMORTAL(victim))
{
count++;
}
}
}
}
if (count == 0)
{
stop_hating(ch);
stop_hunting(ch);
do_yell(ch, "Lost my target, no new ones sited, standing down.");
return;
}
num = number_range(1, count);
for (victim = ch->in_room->first_person; victim; victim = victim->next_in_room)
{
if ((xIS_SET(ch->miflags, KM_ATTACKC) && get_wear_cloak(victim)) ||
(xIS_SET(ch->miflags, KM_ATTACKH) && get_wear_hidden_cloak(victim)))
{
if (IN_SAME_ROOM(ch, victim))
{
if (IS_NPC(victim))
ht = victim->m4;
else
ht = victim->pcdata->hometown;
if (x == num && can_see_map(ch, victim) && !is_safe(ch, victim) && ch->m4 != ht && !IS_IMMORTAL(victim))
{
hunt_message(ch, victim, 3);
start_hunting(ch, victim);
return;
}
else
{
if (can_see_map(ch, victim) && !is_safe(ch, victim) && ch->m4 != ht && !IS_IMMORTAL(victim))
x++;
}
}
}
}
}
}
// 0 is out of Battle, 1 is while on map, range is different
void find_next_hunt(CHAR_DATA * ch, int type)
{
DESCRIPTOR_DATA *d;
CHAR_DATA *victim;
int count = 0;
int x = 1;
int num;
int range;
if (type == 0)
range = 10;
else
range = 10;
if (xIS_SET(ch->act, ACT_MILITARY)) //They hunt mobs too, different function
{
find_next_target(ch);
return;
}
for (d = first_descriptor; d; d = d->next)
{
if (d->connected == CON_PLAYING && d->character->in_room && d->newstate != 2)
victim = d->character;
else
continue;
if (victim->coord->x > -1 || victim->coord->y > -1 || victim->map > -1)
{
if (abs(ch->coord->x - victim->coord->x) <= range && abs(ch->coord->y - victim->coord->y) <= range)
{
if (victim->map == ch->map && can_see(ch, victim) && victim->level < LEVEL_IMMORTAL)
{
count++;
}
}
}
}
if (count == 0)
{
extract_char(ch, TRUE);
return;
}
num = number_range(1, count);
for (d = first_descriptor; d; d = d->next)
{
if (d->connected == CON_PLAYING && d->character->in_room && d->newstate != 2)
victim = d->character;
else
continue;
if (victim->coord->x > -1 || victim->coord->y > -1 || victim->map > -1)
{
if (abs(ch->coord->x - victim->coord->x) <= range && abs(ch->coord->y - victim->coord->y) <= range)
{
if (x == num && (ch->map == victim->map && victim->level < LEVEL_IMMORTAL && can_see(ch, victim)) )
{
hunt_message(ch, victim, range + 1);
start_hunting(ch, victim);
start_hating(ch, victim);
return;
}
else
{
if (ch->map == victim->map && victim->level < LEVEL_IMMORTAL && can_see(ch, victim))
x++;
}
}
}
}
}
bool find_sector(CHAR_DATA * ch, int sector)
{
if (IS_ONMAP_FLAG(ch))
{
if (map_sector[ch->map][ch->coord->x][ch->coord->y] == sector)
{
return TRUE;
}
}
else
{
if (ch->in_room->sector_type == sector)
{
return TRUE;
}
}
return FALSE;
}
/*
* Retrieve a character's carry capacity.
* Vastly reduced (finally) due to containers -Thoric
*/
int can_carry_n(CHAR_DATA * ch)
{
int penalty = 0;
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return 1000;
if (IS_NPC(ch) && (xIS_SET(ch->act, ACT_PET) || xIS_SET(ch->act, ACT_MOUNTSAVE)))
return 0;
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL))
return 1000;
if (get_eq_char(ch, WEAR_WIELD))
++penalty;
if (get_eq_char(ch, WEAR_DUAL_WIELD))
++penalty;
if (get_eq_char(ch, WEAR_MISSILE_WIELD))
++penalty;
if (get_eq_char(ch, WEAR_NOCKED))
++penalty;
if (get_eq_char(ch, WEAR_SHIELD))
++penalty;
return URANGE(8, 8 + get_curr_dex(ch) - 12 - penalty, 20);
}
/*
* Retrieve a character's carry capacity.
*/
int can_carry_w(CHAR_DATA * ch)
{
int level = POINT_LEVEL(LEARNED(ch, gsn_featherback), MASTERED(ch, gsn_featherback));
int weight;
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return 1000000;
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_MOUNTSAVE))
return str_app[get_curr_str(ch)].carry*2;
if (IS_NPC(ch) && xIS_SET(ch->act, ACT_IMMORTAL))
return 1000000;
weight = str_app[get_curr_str(ch)].carry;
if (level > 0)
{
weight += weight * UMIN(40, level/2) / 100;
}
return weight;
}
/*
* See if a player/mob can take a piece of prototype eq -Thoric
*/
bool can_take_proto(CHAR_DATA * ch)
{
if (IS_IMMORTAL(ch))
return TRUE;
else if (IS_NPC(ch) && xIS_SET(ch->act, ACT_PROTOTYPE))
return TRUE;
else
return FALSE;
}
/*
* See if a string is one of the names of an object.
*/
bool is_name(const char *str, char *namelist)
{
char name[MIL];
for (;;)
{
namelist = one_argument(namelist, name);
if (name[0] == '\0')
return FALSE;
if (!str_cmp(str, name))
return TRUE;
}
}
/* Will count users on furniture -- Xerves */
int count_users(OBJ_DATA * obj)
{
CHAR_DATA *fch;
int count = 0;
if (obj->in_room == NULL)
return 0;
for (fch = obj->in_room->first_person; fch != NULL; fch = fch->next_in_room)
if (fch->on == obj)
count++;
return count;
}
int max_weight(OBJ_DATA * obj)
{
CHAR_DATA *fch;
int weight = 0;
if (obj->in_room == NULL)
return 200000;
for (fch = obj->in_room->first_person; fch != NULL; fch = fch->next_in_room)
if (fch->on == obj)
weight = weight + fch->weight;
return weight;
}
bool is_name_prefix(const char *str, char *namelist)
{
char name[MIL];
for (;;)
{
namelist = one_argument(namelist, name);
if (name[0] == '\0')
return FALSE;
if (!str_prefix(str, name))
return TRUE;
}
}
/*
* See if a string is one of the names of an object. -Thoric
* Treats a dash as a word delimiter as well as a space
*/
bool is_name2(const char *str, char *namelist)
{
char name[MIL];
for (;;)
{
namelist = one_argument2(namelist, name);
if (name[0] == '\0')
return FALSE;
if (!str_cmp(str, name))
return TRUE;
}
}
bool is_name2_prefix(const char *str, char *namelist)
{
char name[MIL];
for (;;)
{
namelist = one_argument2(namelist, name);
if (name[0] == '\0')
return FALSE;
if (!str_prefix(str, name))
return TRUE;
}
}
/* -Thoric
* Checks if str is a name in namelist supporting multiple keywords
*/
bool nifty_is_name(char *str, char *namelist)
{
char name[MIL];
if (!str || str[0] == '\0')
return FALSE;
for (;;)
{
str = one_argument2(str, name);
if (name[0] == '\0')
return TRUE;
if (!is_name2(name, namelist))
return FALSE;
}
}
bool nifty_is_name_prefix(char *str, char *namelist)
{
char name[MIL];
if (!str || str[0] == '\0')
return FALSE;
for (;;)
{
str = one_argument2(str, name);
if (name[0] == '\0')
return TRUE;
if (!is_name2_prefix(name, namelist))
return FALSE;
}
}
void room_affect(ROOM_INDEX_DATA * pRoomIndex, AFFECT_DATA * paf, bool fAdd)
{
if (fAdd)
{
switch (paf->location)
{
case APPLY_ROOMFLAG:
case APPLY_SECTORTYPE:
break;
case APPLY_ROOMLIGHT:
pRoomIndex->light += paf->modifier;
break;
case APPLY_TELEVNUM:
case APPLY_TELEDELAY:
break;
}
}
else
{
switch (paf->location)
{
case APPLY_ROOMFLAG:
case APPLY_SECTORTYPE:
break;
case APPLY_ROOMLIGHT:
pRoomIndex->light -= paf->modifier;
break;
case APPLY_TELEVNUM:
case APPLY_TELEDELAY:
break;
}
}
}
/*
* Modify a skill (hopefully) properly -Thoric
*
* On "adding" a skill modifying affect, the value set is unimportant
* upon removing the affect, the skill it enforced to a proper range.
*/
void modify_skill(CHAR_DATA * ch, int sn, int mod, bool fAdd)
{
if (!IS_NPC(ch))
{
if (fAdd)
ch->pcdata->learned[sn] += mod;
else
ch->pcdata->learned[sn] = URANGE(0, ch->pcdata->learned[sn] + mod, MAX_SKPOINTS);
}
}
int base_resis_values(CHAR_DATA *ch, int type)
{
int fire, water, air, earth, energy, holy, unholy, nonmagic, magic, poison, paralysis;
fire=water=air=earth=energy=holy=unholy=nonmagic=magic=poison=paralysis=100;
if (IS_SET(ch->elementb, ELEMENT_FIRE))
{
fire -=25;
water +=50;
}
if (IS_SET(ch->elementb, ELEMENT_WATER))
{
fire +=35;
water -=20;
}
if (IS_SET(ch->elementb, ELEMENT_AIR))
{
air -=35;
earth +=50;
}
if (IS_SET(ch->elementb, ELEMENT_EARTH))
{
air +=35;
earth -=25;
}
if (IS_SET(ch->elementb, ELEMENT_ENERGY))
{
energy -=40;
air +=15;
earth +=15;
fire +=15;
water +=15;
}
if (IS_SET(ch->elementb, ELEMENT_DIVINE))
{
holy -=60;
unholy +=200;
energy -= 10;
air -=10;
earth -=10;
fire -=10;
water -=10;
}
if (IS_SET(ch->elementb, ELEMENT_UNHOLY))
{
unholy -=60;
holy +=200;
energy -= 10;
air -=10;
earth -=10;
fire -=10;
water -=10;
}
if (ch->race == RACE_OGRE)
{
nonmagic -= 20;
fire -= 25;
water -= 30;
magic += 100;
poison -= 30;
paralysis -= 30;
}
if (ch->race == RACE_DWARF)
{
water -= 25;
}
if (ch->race == RACE_HOBBIT)
{
fire -= 25;
}
if (ch->race == RACE_FAIRY)
{
magic -= 35;
nonmagic += 50;
}
if (type == 1)
return fire;
if (type == 2)
return water;
if (type == 3)
return air;
if (type == 4)
return earth;
if (type == 5)
return energy;
if (type == 6)
return holy;
if (type == 7)
return unholy;
if (type == 8)
return nonmagic;
if (type == 9)
return magic;
if (type == 10)
return poison;
if (type == 11)
return paralysis;
return 100;
}
/*
* Apply or remove an affect to a character.
*/
void affect_modify(CHAR_DATA * ch, AFFECT_DATA * paf, sh_int fAdd)
{
OBJ_DATA *wield;
int mod;
sh_int eq = 0;
struct skill_type *skill;
ch_ret retcode;
int resist;
int susc;
int diff;
//AFFECT_DATA *saf;
mod = paf->modifier;
if (fAdd > 1)
{
fAdd -= 2;
eq = 1;
}
if (fAdd)
{
xSET_BITS(ch->affected_by, paf->bitvector);
if (paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL)
{
mod = abs(mod);
if (IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SPELL)
xSET_BIT(ch->affected_by, AFF_RECURRINGSPELL);
else
bug("affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d", ch->name, mod);
return;
}
}
else
{
xREMOVE_BITS(ch->affected_by, paf->bitvector);
/*
* might be an idea to have a duration removespell which returns
* the spell after the duration... but would have to store
* the removed spell's information somewhere... -Thoric
* (Though we could keep the affect, but disable it for a duration)
*/
if ((paf->location % REVERSE_APPLY) == APPLY_REMOVESPELL)
return;
if (paf->location % REVERSE_APPLY == APPLY_RECURRINGSPELL)
{
mod = abs(mod);
if (!IS_VALID_SN(mod) || (skill = skill_table[mod]) == NULL || skill->type != SKILL_SPELL)
bug("affect_modify(%s) APPLY_RECURRINGSPELL with bad sn %d", ch->name, mod);
xREMOVE_BIT(ch->affected_by, AFF_RECURRINGSPELL);
return;
}
switch (paf->location % REVERSE_APPLY)
{
case APPLY_AFFECT:
REMOVE_BIT(ch->affected_by.bits[0], mod);
return;
case APPLY_EXT_AFFECT:
xREMOVE_BIT(ch->affected_by, mod);
return;
case APPLY_RESISTANT:
REMOVE_BIT(ch->resistant, mod);
return;
case APPLY_IMMUNE:
REMOVE_BIT(ch->immune, mod);
return;
case APPLY_SUSCEPTIBLE:
REMOVE_BIT(ch->susceptible, mod);
return;
case APPLY_WEARSPELL: /* affect only on wear */
return;
case APPLY_REMOVE:
SET_BIT(ch->affected_by.bits[0], mod);
return;
}
mod = 0 - mod;
}
switch (paf->location % REVERSE_APPLY)
{
default:
bug("Affect_modify: unknown location %d.", paf->location);
return;
case APPLY_NONE:
break;
case APPLY_ARMOR:
ch->apply_armor += mod;
break;
case APPLY_SHIELD:
ch->apply_shield += mod;
break;
case APPLY_STONE:
ch->apply_stone += mod;
break;
case APPLY_SANCTIFY:
ch->apply_sanctify += mod;
break;
case APPLY_WMOD:
if (!fAdd)
{
if (mod == -ch->apply_wmod)
ch->apply_wmod += mod;
if (ch->apply_wmod < 0)
ch->apply_wmod = 0;
}
else
{
if (mod < ch->apply_wmod || ch->apply_wmod == 0)
{
ch->apply_wmod = mod;
}
}
break;
case APPLY_RENERGY:
resist = (ch->apply_res_energy[1] == 0 ? 100 : ch->apply_res_energy[1]);
susc = (ch->apply_res_energy[2] == 0 ? 100 : ch->apply_res_energy[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_energy[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_energy[1])
ch->apply_res_energy[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_energy[2])
ch->apply_res_energy[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_energy[1] = 100;
diff = base_resis_values(ch, 5)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_energy[2]) //Susc
{
ch->apply_res_energy[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_energy[1]) //Resist
{
ch->apply_res_energy[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_energy[1] = -500;
}
resist = (ch->apply_res_energy[1] == 0 ? 100 : ch->apply_res_energy[1]);
susc = (ch->apply_res_energy[2] == 0 ? 100 : ch->apply_res_energy[2]);
if (ch->apply_res_energy[1] == -500)
ch->apply_res_energy[0] = -500;
else
ch->apply_res_energy[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RWATER:
resist = (ch->apply_res_water[1] == 0 ? 100 : ch->apply_res_water[1]);
susc = (ch->apply_res_water[2] == 0 ? 100 : ch->apply_res_water[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_water[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_water[1])
ch->apply_res_water[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_water[2])
ch->apply_res_water[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_water[1] = 100;
diff = base_resis_values(ch, 2)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_water[2]) //Susc
{
ch->apply_res_water[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_water[1]) //Resist
{
ch->apply_res_water[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_water[1] = -500;
}
resist = (ch->apply_res_water[1] == 0 ? 100 : ch->apply_res_water[1]);
susc = (ch->apply_res_water[2] == 0 ? 100 : ch->apply_res_water[2]);
if (ch->apply_res_water[1] == -500)
ch->apply_res_water[0] = -500;
else
ch->apply_res_water[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_REARTH:
resist = (ch->apply_res_earth[1] == 0 ? 100 : ch->apply_res_earth[1]);
susc = (ch->apply_res_earth[2] == 0 ? 100 : ch->apply_res_earth[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_earth[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_earth[1])
ch->apply_res_earth[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_earth[2])
ch->apply_res_earth[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_earth[1] = 100;
diff = base_resis_values(ch, 4)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_earth[2]) //Susc
{
ch->apply_res_earth[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_earth[1]) //Resist
{
ch->apply_res_earth[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_earth[1] = -500;
}
resist = (ch->apply_res_earth[1] == 0 ? 100 : ch->apply_res_earth[1]);
susc = (ch->apply_res_earth[2] == 0 ? 100 : ch->apply_res_earth[2]);
if (ch->apply_res_earth[1] == -500)
ch->apply_res_earth[0] = -500;
else
ch->apply_res_earth[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RAIR:
resist = (ch->apply_res_air[1] == 0 ? 100 : ch->apply_res_air[1]);
susc = (ch->apply_res_air[2] == 0 ? 100 : ch->apply_res_air[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_air[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_air[1])
ch->apply_res_air[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_air[2])
ch->apply_res_air[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_air[1] = 100;
diff = base_resis_values(ch, 3)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_air[2]) //Susc
{
ch->apply_res_air[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_air[1]) //Resist
{
ch->apply_res_air[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_air[1] = -500;
}
resist = (ch->apply_res_air[1] == 0 ? 100 : ch->apply_res_air[1]);
susc = (ch->apply_res_air[2] == 0 ? 100 : ch->apply_res_air[2]);
if (ch->apply_res_air[1] == -500)
ch->apply_res_air[0] = -500;
else
ch->apply_res_air[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RFIRE:
resist = (ch->apply_res_fire[1] == 0 ? 100 : ch->apply_res_fire[1]);
susc = (ch->apply_res_fire[2] == 0 ? 100 : ch->apply_res_fire[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_fire[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_fire[1])
ch->apply_res_fire[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_fire[2])
ch->apply_res_fire[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_fire[1] = 100;
diff = base_resis_values(ch, 1)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_fire[2]) //Susc
{
ch->apply_res_fire[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_fire[1]) //Resist
{
ch->apply_res_fire[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_fire[1] = -500;
}
resist = (ch->apply_res_fire[1] == 0 ? 100 : ch->apply_res_fire[1]);
susc = (ch->apply_res_fire[2] == 0 ? 100 : ch->apply_res_fire[2]);
if (ch->apply_res_fire[1] == -500)
ch->apply_res_fire[0] = -500;
else
ch->apply_res_fire[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RMAGIC:
resist = (ch->apply_res_magic[1] == 0 ? 100 : ch->apply_res_magic[1]);
susc = (ch->apply_res_magic[2] == 0 ? 100 : ch->apply_res_magic[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_magic[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_magic[1])
ch->apply_res_magic[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_magic[2])
ch->apply_res_magic[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_magic[1] = 100;
diff = base_resis_values(ch, 9)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_magic[2]) //Susc
{
ch->apply_res_magic[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_magic[1]) //Resist
{
ch->apply_res_magic[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_magic[1] = -500;
}
resist = (ch->apply_res_magic[1] == 0 ? 100 : ch->apply_res_magic[1]);
susc = (ch->apply_res_magic[2] == 0 ? 100 : ch->apply_res_magic[2]);
if (ch->apply_res_magic[1] == -500)
ch->apply_res_magic[0] = -500;
else
ch->apply_res_magic[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RNONMAGIC:
resist = (ch->apply_res_nonmagic[1] == 0 ? 100 : ch->apply_res_nonmagic[1]);
susc = (ch->apply_res_nonmagic[2] == 0 ? 100 : ch->apply_res_nonmagic[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_nonmagic[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_nonmagic[1])
ch->apply_res_nonmagic[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_nonmagic[2])
ch->apply_res_nonmagic[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_nonmagic[1] = 100;
diff = base_resis_values(ch, 8)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_nonmagic[2]) //Susc
{
ch->apply_res_nonmagic[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_nonmagic[1]) //Resist
{
ch->apply_res_nonmagic[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_nonmagic[1] = -500;
}
resist = (ch->apply_res_nonmagic[1] == 0 ? 100 : ch->apply_res_nonmagic[1]);
susc = (ch->apply_res_nonmagic[2] == 0 ? 100 : ch->apply_res_nonmagic[2]);
if (ch->apply_res_nonmagic[1] == -500)
ch->apply_res_nonmagic[0] = -500;
else
ch->apply_res_nonmagic[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RBLUNT:
resist = (ch->apply_res_blunt[1] == 0 ? 100 : ch->apply_res_blunt[1]);
susc = (ch->apply_res_blunt[2] == 0 ? 100 : ch->apply_res_blunt[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_blunt[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_blunt[1])
ch->apply_res_blunt[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_blunt[2])
ch->apply_res_blunt[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_blunt[1] = 100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_blunt[2]) //Susc
{
ch->apply_res_blunt[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_blunt[1]) //Resist
{
ch->apply_res_blunt[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_blunt[1] = -500;
}
resist = (ch->apply_res_blunt[1] == 0 ? 100 : ch->apply_res_blunt[1]);
susc = (ch->apply_res_blunt[2] == 0 ? 100 : ch->apply_res_blunt[2]);
if (ch->apply_res_blunt[1] == -500)
ch->apply_res_blunt[0] = -500;
else
ch->apply_res_blunt[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RPIERCE:
resist = (ch->apply_res_pierce[1] == 0 ? 100 : ch->apply_res_pierce[1]);
susc = (ch->apply_res_pierce[2] == 0 ? 100 : ch->apply_res_pierce[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_pierce[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_pierce[1])
ch->apply_res_pierce[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_pierce[2])
ch->apply_res_pierce[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_pierce[1] = 100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_pierce[2]) //Susc
{
ch->apply_res_pierce[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_pierce[1]) //Resist
{
ch->apply_res_pierce[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_pierce[1] = -500;
}
resist = (ch->apply_res_pierce[1] == 0 ? 100 : ch->apply_res_pierce[1]);
susc = (ch->apply_res_pierce[2] == 0 ? 100 : ch->apply_res_pierce[2]);
if (ch->apply_res_pierce[1] == -500)
ch->apply_res_pierce[0] = -500;
else
ch->apply_res_pierce[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RSLASH:
resist = (ch->apply_res_slash[1] == 0 ? 100 : ch->apply_res_slash[1]);
susc = (ch->apply_res_slash[2] == 0 ? 100 : ch->apply_res_slash[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_slash[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_slash[1])
ch->apply_res_slash[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_slash[2])
ch->apply_res_slash[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_slash[1] = 100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_slash[2]) //Susc
{
ch->apply_res_slash[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_slash[1]) //Resist
{
ch->apply_res_slash[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_slash[1] = -500;
}
resist = (ch->apply_res_slash[1] == 0 ? 100 : ch->apply_res_slash[1]);
susc = (ch->apply_res_slash[2] == 0 ? 100 : ch->apply_res_slash[2]);
if (ch->apply_res_slash[1] == -500)
ch->apply_res_slash[0] = -500;
else
ch->apply_res_slash[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RPOISON:
resist = (ch->apply_res_poison[1] == 0 ? 100 : ch->apply_res_poison[1]);
susc = (ch->apply_res_poison[2] == 0 ? 100 : ch->apply_res_poison[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_poison[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_poison[1])
ch->apply_res_poison[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_poison[2])
ch->apply_res_poison[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_poison[1] = 100;
diff = base_resis_values(ch, 10)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_poison[2]) //Susc
{
ch->apply_res_poison[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_poison[1]) //Resist
{
ch->apply_res_poison[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_poison[1] = -500;
}
resist = (ch->apply_res_poison[1] == 0 ? 100 : ch->apply_res_poison[1]);
susc = (ch->apply_res_poison[2] == 0 ? 100 : ch->apply_res_poison[2]);
if (ch->apply_res_poison[1] == -500)
ch->apply_res_poison[0] = -500;
else
ch->apply_res_poison[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RPARALYSIS:
resist = (ch->apply_res_paralysis[1] == 0 ? 100 : ch->apply_res_paralysis[1]);
susc = (ch->apply_res_paralysis[2] == 0 ? 100 : ch->apply_res_paralysis[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_paralysis[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_paralysis[1])
ch->apply_res_paralysis[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_paralysis[2])
ch->apply_res_paralysis[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_paralysis[1] = 100;
diff = base_resis_values(ch, 11)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_paralysis[2]) //Susc
{
ch->apply_res_poison[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_paralysis[1]) //Resist
{
ch->apply_res_paralysis[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_paralysis[1] = -500;
}
resist = (ch->apply_res_paralysis[1] == 0 ? 100 : ch->apply_res_paralysis[1]);
susc = (ch->apply_res_paralysis[2] == 0 ? 100 : ch->apply_res_paralysis[2]);
if (ch->apply_res_paralysis[1] == -500)
ch->apply_res_paralysis[0] = -500;
else
ch->apply_res_paralysis[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RHOLY:
resist = (ch->apply_res_holy[1] == 0 ? 100 : ch->apply_res_holy[1]);
susc = (ch->apply_res_holy[2] == 0 ? 100 : ch->apply_res_holy[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_holy[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_holy[1])
ch->apply_res_holy[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_holy[2])
ch->apply_res_holy[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_holy[1] = 100;
diff = base_resis_values(ch, 6)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_holy[2]) //Susc
{
ch->apply_res_holy[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_holy[1]) //Resist
{
ch->apply_res_holy[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_holy[1] = -500;
}
resist = (ch->apply_res_holy[1] == 0 ? 100 : ch->apply_res_holy[1]);
susc = (ch->apply_res_holy[2] == 0 ? 100 : ch->apply_res_holy[2]);
if (ch->apply_res_holy[1] == -500)
ch->apply_res_holy[0] = -500;
else
ch->apply_res_holy[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RUNHOLY:
resist = (ch->apply_res_unholy[1] == 0 ? 100 : ch->apply_res_unholy[1]);
susc = (ch->apply_res_unholy[2] == 0 ? 100 : ch->apply_res_unholy[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_unholy[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_unholy[1])
ch->apply_res_unholy[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_unholy[2])
ch->apply_res_unholy[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_unholy[1] = 100;
diff = base_resis_values(ch, 7)-100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_unholy[2]) //Susc
{
ch->apply_res_unholy[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_unholy[1]) //Resist
{
ch->apply_res_unholy[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_unholy[1] = -500;
}
resist = (ch->apply_res_unholy[1] == 0 ? 100 : ch->apply_res_unholy[1]);
susc = (ch->apply_res_unholy[2] == 0 ? 100 : ch->apply_res_unholy[2]);
if (ch->apply_res_unholy[1] == -500)
ch->apply_res_unholy[0] = -500;
else
ch->apply_res_unholy[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_RUNDEAD:
resist = (ch->apply_res_undead[1] == 0 ? 100 : ch->apply_res_undead[1]);
susc = (ch->apply_res_undead[2] == 0 ? 100 : ch->apply_res_undead[2]);
//Getting the natural "susc/resist" to add back in later...
diff = (ch->apply_res_undead[0] + (100-resist) - (susc-100)) - 100;
if (!fAdd)
{
if (mod == 0 || mod == -1) //0 and 1 will not work
;
if (mod > -100) //Resist
{
if (mod == -ch->apply_res_undead[1])
ch->apply_res_undead[1] = 100;
}
if (mod < -100) //Susc
{
if (mod == -ch->apply_res_undead[2])
ch->apply_res_undead[2] = 100;
}
if (mod == 1) //Immune
{
ch->apply_res_undead[1] = 100;
}
}
else
{
if (mod > 100 && mod > ch->apply_res_undead[2]) //Susc
{
ch->apply_res_undead[2] = mod;
}
if (mod < 100 && mod > 1 && mod < ch->apply_res_undead[1]) //Resist
{
ch->apply_res_undead[1] = mod;
}
if (mod == -1) //Immune
ch->apply_res_undead[1] = -500;
}
resist = (ch->apply_res_undead[1] == 0 ? 100 : ch->apply_res_undead[1]);
susc = (ch->apply_res_undead[2] == 0 ? 100 : ch->apply_res_undead[2]);
if (ch->apply_res_undead[1] == -500)
ch->apply_res_undead[0] = -500;
else
ch->apply_res_undead[0] = 100 + diff - (100-resist) + (susc-100);
break;
case APPLY_MANAFUSE:
if (mod > ch->apply_manafuse)
{
ch->apply_manafuse = mod;
}
if (mod < 0 && mod + ch->apply_manafuse == 0)
ch->apply_manafuse = 0;
break;
case APPLY_FASTING:
if (mod > ch->apply_fasting)
{
ch->apply_fasting = mod;
}
if (mod < 0 && mod + ch->apply_fasting == 0)
ch->apply_fasting = 0;
break;
case APPLY_MANASHELL:
if (mod > ch->apply_manashell)
{
ch->apply_manashell = mod;
}
if (mod < 0 && mod + ch->apply_manashell == 0)
ch->apply_manashell = 0;
break;
case APPLY_MANASHIELD:
if (mod > ch->apply_manashield)
{
ch->apply_manashield = mod;
}
if (mod < 0 && mod + ch->apply_manashield == 0)
ch->apply_manashield = 0;
break;
case APPLY_MANAGUARD:
if (mod > ch->apply_managuard)
{
ch->apply_managuard = mod;
}
if (mod < 0 && mod + ch->apply_managuard == 0)
ch->apply_managuard = 0;
break;
case APPLY_MANABURN:
if (mod > ch->apply_manaburn)
{
ch->apply_manaburn = mod;
}
if (mod < 0 && mod + ch->apply_manaburn == 0)
ch->apply_manaburn = 0;
break;
case APPLY_WEAPONCLAMP:
if (mod > ch->apply_weaponclamp)
{
ch->apply_weaponclamp = mod;
}
if (mod < 0 && mod + ch->apply_weaponclamp == 0)
ch->apply_weaponclamp = 0;
break;
case APPLY_ARROWCATCH:
if (mod > ch->apply_arrowcatch)
{
ch->apply_arrowcatch = mod;
}
if (mod < 0 && mod + ch->apply_arrowcatch == 0)
ch->apply_arrowcatch = 0;
break;
case APPLY_BRACING:
if (mod > ch->apply_bracing)
{
ch->apply_bracing = mod;
}
if (mod < 0 && mod + ch->apply_bracing == 0)
ch->apply_bracing = 0;
break;
case APPLY_HARDENING:
if (mod > ch->apply_hardening)
{
ch->apply_hardening = mod;
}
if (mod < 0 && mod + ch->apply_hardening == 0)
ch->apply_hardening = 0;
break;
case APPLY_TOHIT:
ch->apply_tohit += mod;
break;
case APPLY_MANATICK:
if (mod > ch->managen)
{
ch->managen = mod;
}
if (mod < 0 && mod + ch->managen == 0)
ch->managen = 0;
break;
case APPLY_HPTICK:
if (mod > ch->hpgen)
{
ch->hpgen = mod;
}
if (mod < 0 && mod + ch->hpgen == 0)
ch->hpgen = 0;
break;
case APPLY_STR:
ch->mod_str += mod;
break;
case APPLY_DEX:
ch->mod_dex += mod;
break;
case APPLY_INT:
ch->mod_int += mod;
break;
case APPLY_WIS:
ch->mod_wis += mod;
break;
case APPLY_CON:
ch->mod_con += mod;
break;
case APPLY_CHA:
ch->mod_cha += mod;
break;
case APPLY_LCK:
ch->mod_lck += mod;
break;
case APPLY_AGI:
ch->mod_agi += mod;
break;
case APPLY_SEX:
ch->sex = (ch->sex + mod) % 3;
if (ch->sex < 0)
ch->sex += 2;
ch->sex = URANGE(0, ch->sex, 2);
break;
/*
* These are unused due to possible problems. Enable at your own risk.
*/
case APPLY_CLASS:
break;
case APPLY_LEVEL:
break;
case APPLY_AGE:
break;
case APPLY_GOLD:
break;
case APPLY_EXP:
break;
/*
* Regular apply types
*/
case APPLY_HEIGHT:
ch->height += mod;
break;
case APPLY_WEIGHT:
ch->weight += mod;
break;
case APPLY_MANA:
/*if (mod > ch->max_mana)
mod = paf->modifier = ch->max_mana;
for (saf = ch->first_affect; saf; saf = saf->next)
{
if ((saf->location % REVERSE_APPLY) == APPLY_MANA && saf != paf && fAdd)
paf->modifier = mod = 0;
}*/
ch->max_mana += mod;
break;
case APPLY_HIT:
/*if (mod > ch->max_hit)
mod = paf->modifier = ch->max_hit;
for (saf = ch->first_affect; saf; saf = saf->next)
{
if ((saf->location % REVERSE_APPLY) == APPLY_HIT && saf != paf && fAdd)
paf->modifier = mod = 0;
} */
ch->max_hit += mod;
break;
case APPLY_MOVE:
ch->max_move += mod;
break;
case APPLY_HITROLL:
ch->hitroll += mod;
break;
case APPLY_DAMROLL:
ch->damroll += mod;
break;
case APPLY_SAVING_POISON:
ch->saving_poison_death += mod;
break;
case APPLY_SAVING_ROD:
ch->saving_wand += mod;
break;
case APPLY_SAVING_PARA:
ch->saving_para_petri += mod;
break;
case APPLY_SAVING_BREATH:
ch->saving_breath += mod;
break;
case APPLY_SAVING_SPELL:
ch->saving_spell_staff += mod;
break;
/*
* Bitvector modifying apply types
*/
case APPLY_AFFECT:
SET_BIT(ch->affected_by.bits[0], mod);
break;
case APPLY_EXT_AFFECT:
xSET_BIT(ch->affected_by, mod);
break;
case APPLY_RESISTANT:
SET_BIT(ch->resistant, mod);
break;
case APPLY_IMMUNE:
SET_BIT(ch->immune, mod);
break;
case APPLY_SUSCEPTIBLE:
SET_BIT(ch->susceptible, mod);
break;
case APPLY_WEAPONSPELL: /* see fight.c */
break;
case APPLY_REMOVE:
REMOVE_BIT(ch->affected_by.bits[0], mod);
break;
/*
* Player condition modifiers
*/
case APPLY_FULL:
if (!IS_NPC(ch))
ch->pcdata->condition[COND_FULL] = URANGE(0, ch->pcdata->condition[COND_FULL] + mod, 48);
break;
case APPLY_THIRST:
if (!IS_NPC(ch))
ch->pcdata->condition[COND_THIRST] = URANGE(0, ch->pcdata->condition[COND_THIRST] + mod, 48);
break;
case APPLY_DRUNK:
if (!IS_NPC(ch))
ch->pcdata->condition[COND_DRUNK] = URANGE(0, ch->pcdata->condition[COND_DRUNK] + mod, 48);
break;
case APPLY_BLOOD:
if (!IS_NPC(ch))
ch->pcdata->condition[COND_BLOODTHIRST] = URANGE(0, ch->pcdata->condition[COND_BLOODTHIRST] + mod, ch->level + 10);
break;
case APPLY_MENTALSTATE:
ch->mental_state = URANGE(-100, ch->mental_state + mod, 100);
break;
case APPLY_EMOTION:
ch->emotional_state = URANGE(-100, ch->emotional_state + mod, 100);
break;
/*
* Specialty modfiers
*/
case APPLY_CONTAGIOUS:
break;
case APPLY_ODOR:
break;
case APPLY_STRIPSN:
if (IS_VALID_SN(mod))
affect_strip(ch, mod);
else
bug("affect_modify: APPLY_STRIPSN invalid sn %d", mod);
break;
/* spell cast upon wear/removal of an object -Thoric */
case APPLY_WEARSPELL:
case APPLY_REMOVESPELL:
if (xIS_SET(ch->in_room->room_flags, ROOM_NO_MAGIC) || wIS_SET(ch, ROOM_NO_MAGIC) || is_immune(ch, -1, RIS_MAGIC)
|| saving_char == ch /* so save/quit doesn't trigger */ || loading_char == ch) /* so loading doesn't trigger */
return;
mod = abs(mod);
if (IS_VALID_SN(mod) && (skill = skill_table[mod]) != NULL && skill->type == SKILL_SPELL)
{
if (skill->target == TAR_IGNORE || skill->target == TAR_OBJ_INV || skill->target == TAR_OBJ_ROOM)
{
bug("APPLY_WEARSPELL trying to apply bad target spell. SN is %d.", mod);
return;
}
if ((retcode = (*skill->spell_fun) (mod, ch->level, ch, ch)) == rCHAR_DIED || char_died(ch))
return;
}
break;
/*
* Skill apply types
*/
case APPLY_PALM: /* not implemented yet */
break;
case APPLY_TRACK:
modify_skill(ch, gsn_track, mod, fAdd);
break;
case APPLY_HIDE:
modify_skill(ch, gsn_hide, mod, fAdd);
break;
case APPLY_STEAL:
modify_skill(ch, gsn_steal, mod, fAdd);
break;
case APPLY_SNEAK:
modify_skill(ch, gsn_sneak, mod, fAdd);
break;
case APPLY_PICK:
modify_skill(ch, gsn_pick_lock, mod, fAdd);
break;
case APPLY_BACKSTAB:
modify_skill(ch, gsn_backstab, mod, fAdd);
break;
case APPLY_DETRAP:
modify_skill(ch, gsn_detrap, mod, fAdd);
break;
case APPLY_DODGE:
modify_skill(ch, gsn_dodge, mod, fAdd);
break;
case APPLY_PEEK:
modify_skill(ch, gsn_peek, mod, fAdd);
break;
case APPLY_SCAN:
modify_skill(ch, gsn_scan, mod, fAdd);
break;
case APPLY_GOUGE:
modify_skill(ch, gsn_gouge, mod, fAdd);
break;
case APPLY_SEARCH:
modify_skill(ch, gsn_search, mod, fAdd);
break;
case APPLY_DIG:
modify_skill(ch, gsn_dig, mod, fAdd);
break;
case APPLY_MOUNT:
break;
case APPLY_DISARM:
modify_skill(ch, gsn_disarm, mod, fAdd);
break;
case APPLY_KICK:
break;
case APPLY_PARRY:
modify_skill(ch, gsn_parry, mod, fAdd);
break;
case APPLY_BASH:
break;
case APPLY_STUN:
modify_skill(ch, gsn_stun, mod, fAdd);
break;
case APPLY_PUNCH:
break;
case APPLY_CLIMB:
modify_skill(ch, gsn_climb, mod, fAdd);
break;
case APPLY_GRIP:
modify_skill(ch, gsn_grip, mod, fAdd);
break;
case APPLY_SCRIBE:
modify_skill(ch, gsn_scribe, mod, fAdd);
break;
case APPLY_BREW:
modify_skill(ch, gsn_brew, mod, fAdd);
break;
case APPLY_COOK:
modify_skill(ch, gsn_cook, mod, fAdd);
break;
/*
* Room apply types
*/
case APPLY_ROOMFLAG:
case APPLY_SECTORTYPE:
case APPLY_ROOMLIGHT:
case APPLY_TELEVNUM:
break;
/*
* Object apply types
*/
}
/*
* Check for weapon wielding.
* Guard against recursion (for weapons with affects).
*/
if (!IS_NPC(ch) && saving_char != ch && (wield = get_eq_char(ch, WEAR_WIELD)) != NULL && get_obj_weight(wield) > str_app[get_curr_str(ch)].wield)
{
static int depth;
if (depth == 0)
{
depth++;
act(AT_ACTION, "You notice your strength decrease thus taking more time to swing your weapon!", ch, wield, NULL, TO_CHAR);
depth--;
}
}
return;
}
/*
* Give an affect to a char.
*/
void affect_to_char(CHAR_DATA * ch, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_new;
if (!ch)
{
bug("Affect_to_char(NULL, %d)", paf ? paf->type : 0);
return;
}
if (!paf)
{
bug("Affect_to_char(%s, NULL)", ch->name);
return;
}
CREATE(paf_new, AFFECT_DATA, 1);
LINK(paf_new, ch->first_affect, ch->last_affect, next, prev);
paf_new->type = paf->type;
paf_new->duration = paf->duration;
paf_new->location = paf->location;
paf_new->modifier = paf->modifier;
paf_new->bitvector = paf->bitvector;
affect_modify(ch, paf_new, TRUE);
return;
}
/*
* Remove an affect from a char.
*/
void affect_remove(CHAR_DATA * ch, AFFECT_DATA * paf)
{
if (!ch->first_affect)
{
bug("Affect_remove(%s, %d): no affect.", ch->name, paf ? paf->type : 0);
return;
}
affect_modify(ch, paf, FALSE);
UNLINK(paf, ch->first_affect, ch->last_affect, next, prev);
DISPOSE(paf);
return;
}
/*
* Strip all affects of a given sn.
*/
void affect_strip(CHAR_DATA * ch, int sn)
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
for (paf = ch->first_affect; paf; paf = paf_next)
{
paf_next = paf->next;
if (paf->type == sn)
affect_remove(ch, paf);
}
return;
}
/*
* Return true if a char is affected by a spell.
*/
bool is_affected(CHAR_DATA * ch, int sn)
{
AFFECT_DATA *paf;
for (paf = ch->first_affect; paf; paf = paf->next)
if (paf->type == sn)
return TRUE;
return FALSE;
}
/*
* Add or enhance an affect.
* Limitations put in place by Thoric, they may be high... but at least
* they're there :)
*/
void affect_join(CHAR_DATA * ch, AFFECT_DATA * paf)
{
AFFECT_DATA *paf_old;
for (paf_old = ch->first_affect; paf_old; paf_old = paf_old->next)
if (paf_old->type == paf->type)
{
paf->duration = UMIN(1000000, paf->duration + paf_old->duration);
if (paf->modifier < 0)
{
if (paf_old->modifier < paf->modifier)
paf->modifier = paf_old->modifier;
}
else if (paf->modifier > 0)
{
if (paf_old->modifier > paf->modifier)
paf->modifier = paf_old->modifier;
}
affect_remove(ch, paf_old);
break;
}
affect_to_char(ch, paf);
return;
}
/*
* Apply only affected and RIS on a char
*/
void aris_affect(CHAR_DATA * ch, AFFECT_DATA * paf)
{
xSET_BITS(ch->affected_by, paf->bitvector);
switch (paf->location % REVERSE_APPLY)
{
case APPLY_AFFECT:
SET_BIT(ch->affected_by.bits[0], paf->modifier);
break;
case APPLY_EXT_AFFECT:
xSET_BIT(ch->affected_by, paf->modifier);
case APPLY_RESISTANT:
SET_BIT(ch->resistant, paf->modifier);
break;
case APPLY_IMMUNE:
SET_BIT(ch->immune, paf->modifier);
break;
case APPLY_SUSCEPTIBLE:
SET_BIT(ch->susceptible, paf->modifier);
break;
}
}
/*
* Update affecteds and RIS for a character in case things get messed.
* This should only really be used as a quick fix until the cause
* of the problem can be hunted down. - FB
* Last modified: June 30, 1997
*
* Quick fix? Looks like a good solution for a lot of problems.
*/
/* Temp mod to bypass immortals so they can keep their mset affects,
* just a band-aid until we get more time to look at it -- Blodkai */
void update_aris(CHAR_DATA * ch)
{
AFFECT_DATA *paf;
OBJ_DATA *obj;
int hiding;
if (IS_NPC(ch) || IS_IMMORTAL(ch))
return;
/* So chars using hide skill will continue to hide */
hiding = IS_AFFECTED(ch, AFF_HIDE);
xCLEAR_BITS(ch->affected_by);
ch->resistant = 0;
ch->immune = 0;
ch->susceptible = 0;
xCLEAR_BITS(ch->no_affected_by);
ch->no_resistant = 0;
ch->no_immune = 0;
ch->no_susceptible = 0;
/* Add in effects from race */
xSET_BITS(ch->affected_by, race_table[ch->race]->affected);
SET_BIT(ch->resistant, race_table[ch->race]->resist);
SET_BIT(ch->susceptible, race_table[ch->race]->suscept);
/* Add in effects from deities */
if (ch->pcdata->deity)
{
if (ch->pcdata->favor > ch->pcdata->deity->affectednum)
xSET_BITS(ch->affected_by, ch->pcdata->deity->affected);
if (ch->pcdata->favor > ch->pcdata->deity->elementnum)
SET_BIT(ch->resistant, ch->pcdata->deity->element);
if (ch->pcdata->favor < ch->pcdata->deity->susceptnum)
SET_BIT(ch->susceptible, ch->pcdata->deity->suscept);
}
/* Add in effect from spells */
for (paf = ch->first_affect; paf; paf = paf->next)
aris_affect(ch, paf);
/* Add in effects from equipment */
for (obj = ch->first_carrying; obj; obj = obj->next_content)
{
if (obj->wear_loc != WEAR_NONE)
{
for (paf = obj->first_affect; paf; paf = paf->next)
aris_affect(ch, paf);
for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
aris_affect(ch, paf);
}
}
/* Add in effects from the room */
if (ch->in_room) /* non-existant char booboo-fix --TRI */
for (paf = ch->in_room->first_affect; paf; paf = paf->next)
aris_affect(ch, paf);
/* Add in effects for polymorph */
if (ch->morph)
{
xSET_BITS(ch->affected_by, ch->morph->affected_by);
SET_BIT(ch->immune, ch->morph->immune);
SET_BIT(ch->resistant, ch->morph->resistant);
SET_BIT(ch->susceptible, ch->morph->suscept);
/* Right now only morphs have no_ things --Shaddai */
xSET_BITS(ch->no_affected_by, ch->morph->no_affected_by);
SET_BIT(ch->no_immune, ch->morph->no_immune);
SET_BIT(ch->no_resistant, ch->morph->no_resistant);
SET_BIT(ch->no_susceptible, ch->morph->no_suscept);
}
/* If they were hiding before, make them hiding again */
if (hiding)
xSET_BIT(ch->affected_by, AFF_HIDE);
return;
}
/*
* Move a char out of a room.
*/
void char_from_room(CHAR_DATA * ch)
{
OBJ_DATA *obj;
AFFECT_DATA *paf;
CMAP_DATA *mch;
if (!ch->in_room)
{
bug("Char_from_room: NULL.", 0);
return;
}
if (!IS_NPC(ch))
--ch->in_room->area->nplayer;
if ((obj = get_eq_char(ch, WEAR_LIGHT)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room->light > 0)
--ch->in_room->light;
/*
* Character's affect on the room
*/
for (paf = ch->first_affect; paf; paf = paf->next)
room_affect(ch->in_room, paf, FALSE);
if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_MAPWINDOW) && ch->in_room->vnum == OVERLAND_SOLAN)
{
ch_printf(ch, "%s", MXPTAG("FRAME Map CLOSE"));
ch->pcdata->xsize = 0;
ch->pcdata->ysize = 0;
}
/*
* Room's affect on the character
*/
if (!char_died(ch))
{
for (paf = ch->in_room->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, FALSE);
if (char_died(ch)) /* could die from removespell, etc */
return;
}
if (IS_NPC(ch))
{
for (mch = first_wilderchar; mch; mch = mch->next)
{
if (mch->mapch == ch && (mch->mapch->coord->x == ch->coord->x && mch->mapch->coord->y == ch->coord->y && mch->mapch->map == ch->map))
{
UNLINK(mch, first_wilderchar, last_wilderchar, next, prev);
top_map_mob--;
}
}
}
UNLINK(ch, ch->in_room->first_person, ch->in_room->last_person, next_in_room, prev_in_room);
ch->was_in_room = ch->in_room;
ch->in_room = NULL;
ch->next_in_room = NULL;
ch->prev_in_room = NULL;
if (!IS_NPC(ch) && get_timer(ch, TIMER_SHOVEDRAG) > 0)
remove_timer(ch, TIMER_SHOVEDRAG);
return;
}
/*
* Enough resources to build? Docks if needed -- Xerves 12/99
*/
bool enough_resources(CHAR_DATA * ch, int hometown, int needed, int ctype)
{
if (needed > ch->pcdata->town->lumber)
{
ch_printf(ch, "You need %d units, your hometown cannot afford that.\n\r", needed);
return FALSE;
}
if (ctype == 0)
ch->pcdata->town->lumber -= needed;
return TRUE;
}
/*
* Move a char into a room.
*/
void char_to_room(CHAR_DATA * ch, ROOM_INDEX_DATA * pRoomIndex)
{
OBJ_DATA *obj;
AFFECT_DATA *paf;
CMAP_DATA *mch;
if (!ch)
{
bug("Char_to_room: NULL ch!", 0);
return;
}
if (!pRoomIndex)
{
bug("Char_to_room: %s -> NULL room! Putting char in limbo (%d)", ch->name, ROOM_VNUM_LIMBO);
/*
* This used to just return, but there was a problem with crashing
* and I saw no reason not to just put the char in limbo. -Narn
*/
pRoomIndex = get_room_index(ROOM_VNUM_LIMBO);
}
ch->in_room = pRoomIndex;
LINK(ch, pRoomIndex->first_person, pRoomIndex->last_person, next_in_room, prev_in_room);
if (IS_NPC(ch) && ch->in_room->vnum == OVERLAND_SOLAN)
{
CREATE(mch, CMAP_DATA, 1);
mch->mapch = ch;
LINK(mch, first_wilderchar, last_wilderchar, next, prev);
top_map_mob++;
}
if (!IS_NPC(ch))
if (++pRoomIndex->area->nplayer > pRoomIndex->area->max_players)
pRoomIndex->area->max_players = pRoomIndex->area->nplayer;
if ((obj = get_eq_char(ch, WEAR_LIGHT)) != NULL && obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
++pRoomIndex->light;
if (ch->pcdata && ch->pcdata->quest && ch->pcdata->quest->questarea == ch->in_room->area
&& ch->pcdata->quest->timeleft > 0 && ch->pcdata->quest->mission == 2)
{
int x;
CHAR_DATA *gch;
ch->pcdata->quest->killed++;
if (ch->pcdata->quest->traveltime > -1)
ch->pcdata->quest->traveltime = 0;
if (pRoomIndex->vnum == pRoomIndex->area->hi_r_vnum) //Win
{
for (x = 0; x <= 5; x++)
{
if (ch->pcdata->quest->player[x] == ch->pcdata->pid)
{
ch_printf(ch, "\n\r^r&CYou have completed your quest, your reward is %d QP^x\n\r\n\r", ch->pcdata->quest->qp[x]);
ch->pcdata->quest_curr += ch->pcdata->quest->qp[x];
ch->pcdata->quest_accum += ch->pcdata->quest->qp[x];
ch->pcdata->quest_wins++;
}
}
for (gch = first_char; gch; gch = gch->next)
{
if (IS_NPC(gch))
continue;
if (gch == ch)
continue;
if (!gch->pcdata->quest)
continue;
if (gch->pcdata->quest->questarea != ch->in_room->area)
continue;
if (gch->pcdata->quest != ch->pcdata->quest)
continue;
for (x = 0; x <= 5; x++)
{
if (gch->pcdata->quest->player[x] == gch->pcdata->pid)
{
ch_printf(gch, "\n\r^r&CYou have completed your quest, your reward is %d QP^x\n\r\n\r", gch->pcdata->quest->qp[x]);
gch->pcdata->quest_curr += gch->pcdata->quest->qp[x];
gch->pcdata->quest_accum += gch->pcdata->quest->qp[x];
gch->pcdata->quest_wins++;
gch->pcdata->quest->timeleft = -1;
gch->pcdata->quest->tillnew = 25;
}
}
}
ch->pcdata->quest->timeleft = -1;
ch->pcdata->quest->tillnew = 25;
}
}
/*
* Room's effect on the character
*/
if (!char_died(ch))
{
for (paf = pRoomIndex->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, TRUE);
if (char_died(ch)) /* could die from a wearspell, etc */
return;
}
/*
* Character's effect on the room
*/
for (paf = ch->first_affect; paf; paf = paf->next)
room_affect(pRoomIndex, paf, TRUE);
if (!IS_NPC(ch) && (check_room_pk(ch) == 1))
{
if (get_timer(ch, TIMER_SHOVEDRAG) > 0)
remove_timer(ch, TIMER_SHOVEDRAG);
add_timer(ch, TIMER_SHOVEDRAG, 4, NULL, 0);/*-12 Seconds-*/
}
/*
* Delayed Teleport rooms -Thoric
* Should be the last thing checked in this function
*/
if (xIS_SET(pRoomIndex->room_flags, ROOM_TELEPORT) && pRoomIndex->tele_delay > 0)
{
TELEPORT_DATA *tele;
for (tele = first_teleport; tele; tele = tele->next)
if (tele->room == pRoomIndex)
return;
CREATE(tele, TELEPORT_DATA, 1);
LINK(tele, first_teleport, last_teleport, next, prev);
tele->room = pRoomIndex;
tele->timer = pRoomIndex->tele_delay;
}
if (ch->on)
{
ch->on = NULL;
ch->position = POS_STANDING;
}
if (ch->mount)
{
ch->mount->on = NULL;
ch->mount->position = POS_STANDING;
}
if (!ch->was_in_room)
ch->was_in_room = ch->in_room;
return;
}
//Checks carrying weight/number, replaced the integer due to it being inaccurate at times
float get_ch_carry_weight(CHAR_DATA *ch)
{
OBJ_DATA *obj;
float weight = 0;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
{
weight += get_obj_weight(obj);
}
if (ch->rider)
{
weight += (float)ch->rider->weight;
weight += get_ch_carry_weight(ch->rider);
}
return weight;
}
int get_ch_carry_number(CHAR_DATA *ch)
{
OBJ_DATA *obj;
int weight = 0;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
{
if (obj->wear_loc == WEAR_NONE)
weight += get_obj_number(obj);
}
return weight;
}
OBJ_DATA *bank_to_char(OBJ_DATA * obj, CHAR_DATA *ch)
{
if (ch != NULL)
{
if (IN_WILDERNESS(ch))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = ch->map;
obj->coord->x = ch->coord->x;
obj->coord->y = ch->coord->y;
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
UNLINK(obj, ch->pcdata->first_bankobj, ch->pcdata->last_bankobj, next_content, prev_content);
obj->carried_by = NULL;
obj->in_room = NULL;
obj->in_obj = NULL;
return obj;
}
OBJ_DATA *townbank_to_char(OBJ_DATA * obj, TOWN_DATA *town, CHAR_DATA *ch)
{
if (ch != NULL)
{
if (IN_WILDERNESS(ch))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = ch->map;
obj->coord->x = ch->coord->x;
obj->coord->y = ch->coord->y;
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
UNLINK(obj, town->first_bankobj, town->last_bankobj, next_content, prev_content);
obj->carried_by = NULL;
obj->in_room = NULL;
obj->in_obj = NULL;
return obj;
}
OBJ_DATA *obj_to_bank(OBJ_DATA * obj, CHAR_DATA *ch)
{
OBJ_DATA *otmp;
OBJ_DATA *oret = NULL;
int grouped = FALSE;
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
for (otmp = ch->pcdata->first_bankobj; otmp; otmp = otmp->next_content)
{
if ((oret = group_object(otmp, obj)) == otmp)
{
grouped = TRUE;
break;
}
}
if (!grouped)
{
LINK(obj, ch->pcdata->first_bankobj, ch->pcdata->last_bankobj, next_content, prev_content);
obj->carried_by = NULL;
obj->in_room = NULL;
obj->in_obj = NULL;
return obj;
}
else
return oret;
}
OBJ_DATA *obj_to_townbank(OBJ_DATA * obj, TOWN_DATA *town)
{
OBJ_DATA *otmp;
OBJ_DATA *oret = NULL;
int grouped = FALSE;
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
for (otmp = town->first_bankobj; otmp; otmp = otmp->next_content)
{
if ((oret = group_object(otmp, obj)) == otmp)
{
grouped = TRUE;
break;
}
}
if (!grouped)
{
LINK(obj, town->first_bankobj, town->last_bankobj, next_content, prev_content);
obj->carried_by = NULL;
obj->in_room = NULL;
obj->in_obj = NULL;
return obj;
}
else
return oret;
}
/*
* Give an obj to a char.
*/
OBJ_DATA *obj_to_char(OBJ_DATA * obj, CHAR_DATA * ch)
{
OBJ_DATA *otmp;
OBJ_DATA *oret = obj;
bool skipgroup, grouped;
int x;
CHAR_DATA *gch;
skipgroup = FALSE;
grouped = FALSE;
if (obj->trap && !IS_NPC(ch))
{
if (obj->trap->uid < START_INV_TRAP)
copy_trap(obj->trap, obj);
}
if (IS_OBJ_STAT(obj, ITEM_PROTOTYPE))
{
if (!IS_IMMORTAL(ch) && (IS_NPC(ch) && !xIS_SET(ch->act, ACT_PROTOTYPE)))
return obj_to_room(obj, ch->in_room, ch);
}
if (ch != NULL)
{
if (IN_WILDERNESS(ch))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = ch->map;
obj->coord->x = ch->coord->x;
obj->coord->y = ch->coord->y;
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
if (loading_char == ch)
{
int x, y;
for (x = 0; x < MAX_WEAR; x++)
for (y = 0; y < MAX_LAYERS; y++)
if (save_equipment[x][y] == obj)
{
skipgroup = TRUE;
break;
}
}
if (!skipgroup)
for (otmp = ch->first_carrying; otmp; otmp = otmp->next_content)
if ((oret = group_object(otmp, obj)) == otmp)
{
grouped = TRUE;
break;
}
if (!grouped)
{
if (!IS_NPC(ch) || !ch->pIndexData->pShop)
{
LINK(obj, ch->first_carrying, ch->last_carrying, next_content, prev_content);
obj->carried_by = ch;
obj->in_room = NULL;
obj->in_obj = NULL;
}
else
{
/* If ch is a shopkeeper, add the obj using an insert sort */
for (otmp = ch->first_carrying; otmp; otmp = otmp->next_content)
{
if (obj->level > otmp->level)
{
INSERT(obj, otmp, ch->first_carrying, next_content, prev_content);
break;
}
else if (obj->level == otmp->level && strcmp(obj->short_descr, otmp->short_descr) < 0)
{
INSERT(obj, otmp, ch->first_carrying, next_content, prev_content);
break;
}
}
if (!otmp)
{
LINK(obj, ch->first_carrying, ch->last_carrying, next_content, prev_content);
}
obj->carried_by = ch;
obj->in_room = NULL;
obj->in_obj = NULL;
}
}
if (obj->item_type == ITEM_QTOKEN)
{
if (!xIS_SET(obj->extra_flags, ITEM_QTOKEN_LOOTED))
{
if (!ch->in_room || (IS_NPC(ch) && ch->pIndexData->vnum >= ch->in_room->area->low_r_vnum && ch->pIndexData->vnum <= ch->in_room->area->hi_r_vnum))
;
else
xSET_BIT(obj->extra_flags, ITEM_QTOKEN_LOOTED);
if (!IS_NPC(ch) && ch->pcdata->quest && ch->pcdata->quest->questarea == ch->in_room->area
&& ch->pcdata->quest->timeleft > 0 && ch->pcdata->quest->mission == 4)
{
ch->pcdata->quest->killed += obj->count;
if (ch->pcdata->quest->traveltime > -1)
ch->pcdata->quest->traveltime = -1;
if (ch->pcdata->quest->killed >= ch->pcdata->quest->tokill) //Win
{
for (x = 0; x <= 5; x++)
{
if (ch->pcdata->quest->player[x] == ch->pcdata->pid)
{
ch_printf(ch, "\n\r^r&CYou have completed your quest, your reward is %d QP^x\n\r\n\r", ch->pcdata->quest->qp[x]);
ch->pcdata->quest_curr += ch->pcdata->quest->qp[x];
ch->pcdata->quest_accum += ch->pcdata->quest->qp[x];
ch->pcdata->quest_wins++;
}
}
for (gch = first_char; gch; gch = gch->next)
{
if (IS_NPC(gch))
continue;
if (gch == ch)
continue;
if (!gch->pcdata->quest)
continue;
if (gch->pcdata->quest->questarea != ch->in_room->area)
continue;
if (gch->pcdata->quest != ch->pcdata->quest)
continue;
for (x = 0; x <= 5; x++)
{
if (gch->pcdata->quest->player[x] == gch->pcdata->pid)
{
ch_printf(gch, "\n\r^r&CYou have completed your quest, your reward is %d QP^x\n\r\n\r", gch->pcdata->quest->qp[x]);
gch->pcdata->quest_curr += gch->pcdata->quest->qp[x];
gch->pcdata->quest_accum += gch->pcdata->quest->qp[x];
gch->pcdata->quest_wins++;
gch->pcdata->quest->timeleft = -1;
gch->pcdata->quest->tillnew = 25;
}
}
}
ch->pcdata->quest->timeleft = -1;
ch->pcdata->quest->tillnew = 25;
}
}
}
}
return (oret ? oret : obj);
}
void check_time_resets(OBJ_DATA *obj)
{
AREA_DATA *pArea;
RESET_DATA *pReset = NULL;
if (xIS_SET(obj->extra_flags, ITEM_TIMERESET))
{
if (obj->carried_by && obj->carried_by->in_room)
pArea = obj->carried_by->in_room->area;
else if (obj->in_obj && obj->in_obj->carried_by && obj->in_obj->carried_by->in_room)
pArea = obj->in_obj->carried_by->in_room->area;
else if (obj->in_room)
pArea = obj->in_room->area;
else if (obj->in_obj && obj->in_obj->in_room)
pArea = obj->in_obj->in_room->area;
else
{
//if no one "was" carrying it, start looping
for (pArea = first_area; pArea; pArea = pArea->next)
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->resettime > 0 && (pReset->command == 'O' || pReset->command == 'P' || pReset->command == 'E' || pReset->command == 'G') && pReset->arg1 == obj->pIndexData->vnum )
{
break;
}
}
if (pReset)
break;
}
}
if (!pReset && pArea)
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->resettime > 0 && (pReset->command == 'O' || pReset->command == 'P' || pReset->command == 'E' || pReset->command == 'G') && pReset->arg1 == obj->pIndexData->vnum)
break;
}
}
if (!pArea || (pArea && !pReset))
{
if (!pArea)
bug("Could not find the area to fit obj %d's reset.", obj->pIndexData->vnum);
else
bug("Could not find the proper Reset for obj %d", obj->pIndexData->vnum);
}
else
{;
pReset->resetlast = time(0);
xREMOVE_BIT(obj->extra_flags, ITEM_TIMERESET);
bug("TIMERESET LOOTED: %d has been looted.", obj->pIndexData->vnum); //just in case some brainful player says an item loaded that did not
fold_area(pArea, pArea->filename, FALSE, 1);
}
}
if (xIS_SET(obj->extra_flags, ITEM_NORESET))
{
if (obj->carried_by && obj->carried_by->in_room)
pArea = obj->carried_by->in_room->area;
else if (obj->in_obj && obj->in_obj->carried_by && obj->in_obj->carried_by->in_room)
pArea = obj->in_obj->carried_by->in_room->area;
else if (obj->in_room)
pArea = obj->in_room->area;
else if (obj->in_obj && obj->in_obj->in_room)
pArea = obj->in_obj->in_room->area;
else
{
//if no one "was" carrying it, start looping
for (pArea = first_area; pArea; pArea = pArea->next)
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->resettime == -1 && (pReset->command == 'O' || pReset->command == 'P' || pReset->command == 'E' || pReset->command == 'G') && pReset->arg1 == obj->pIndexData->vnum )
{
break;
}
}
if (pReset)
break;
}
}
if (!pReset && pArea)
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->resettime == -1 && (pReset->command == 'O' || pReset->command == 'P' || pReset->command == 'E' || pReset->command == 'G') && pReset->arg1 == obj->pIndexData->vnum)
break;
}
}
if (!pArea || (pArea && !pReset))
{
if (!pArea)
bug("Could not find the area to fit obj %d's reset.", obj->pIndexData->vnum);
else
bug("Could not find the proper Reset for obj %d", obj->pIndexData->vnum);
}
else
{
delete_reset(pArea, pReset);
xREMOVE_BIT(obj->extra_flags, ITEM_NORESET);
bug("NORESET LOOTED: %d has been looted.", obj->pIndexData->vnum); //just in case some brainful player says an item loaded that did not
fold_area(pArea, pArea->filename, FALSE, 1);
}
}
}
/*
* Take an obj from its character.
*/
void obj_from_char(OBJ_DATA * obj)
{
CHAR_DATA *ch;
if ((ch = obj->carried_by) == NULL)
{
bug("Obj_from_char: null ch.", 0);
return;
}
if (obj->wear_loc != WEAR_NONE)
unequip_char(ch, obj);
/* obj may drop during unequip... */
if (!obj->carried_by)
return;
UNLINK(obj, ch->first_carrying, ch->last_carrying, next_content, prev_content);
if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
empty_obj(obj, NULL, NULL);
check_time_resets(obj);
obj->in_room = NULL;
obj->carried_by = NULL;
obj->possessed_by = NULL;
return;
}
/*
* Find the ac value of an obj, including position effect.
*/
int apply_ac(OBJ_DATA * obj, int iWear)
{
return 0;
}
/*
* Find a piece of eq on a character.
* Will pick the top layer if clothing is layered. -Thoric
*/
OBJ_DATA *get_eq_char(CHAR_DATA * ch, int iWear)
{
OBJ_DATA *obj, *maxobj = NULL;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
{
if (obj->wear_loc == iWear)
{
if (!obj->pIndexData->layers)
{
return obj;
}
else
{
if (!maxobj || obj->pIndexData->layers > maxobj->pIndexData->layers)
maxobj = obj;
}
}
}
return maxobj;
}
/*
* Equip a char with an obj.
*/
void equip_char(CHAR_DATA * ch, OBJ_DATA * obj, int iWear)
{
AFFECT_DATA *paf;
OBJ_DATA *otmp;
if ((otmp = get_eq_char(ch, iWear)) != NULL && (!otmp->pIndexData->layers || !obj->pIndexData->layers))
{
if (global_drop_equip_message == 0)
bug("Equip_char: already equipped (%d).", iWear);
return;
}
if (IS_OBJ_STAT(obj, ITEM_KINGDOMEQ) && !IS_OBJ_STAT(obj, ITEM_LODGED))
{
if (!IS_NPC(ch) || (IS_NPC(ch) && !xIS_SET(ch->act, ACT_MILITARY)))
{
send_to_char("Cannot equip this item, it is kingdom eq\n\r", ch);
return;
}
}
separate_obj(obj); /* just in case */
obj->wear_loc = iWear;
for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, 3);
for (paf = obj->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, 3);
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room)
++ch->in_room->light;
check_for_trap(ch, obj, -1, NEW_TRAP_WEAROBJ);
return;
}
/*
* Unequip a char with an obj.
*/
void unequip_char(CHAR_DATA * ch, OBJ_DATA * obj)
{
AFFECT_DATA *paf;
if (obj->wear_loc == WEAR_NONE)
{
if (global_drop_equip_message == 0)
bug("Unequip_char: already unequipped.", 0);
return;
}
if (obj->item_type == ITEM_PROJECTILE)
REMOVE_OBJ_STAT(obj, ITEM_LODGED);
obj->wear_loc = -1;
for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, 2);
if (obj->carried_by)
for (paf = obj->first_affect; paf; paf = paf->next)
affect_modify(ch, paf, 2);
update_aris(ch);
if (!obj->carried_by)
{
bug("here");
return;
}
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0 && ch->in_room && ch->in_room->light > 0)
--ch->in_room->light;
check_for_trap(ch, obj, TRAP_PUT, NEW_TRAP_REMOVEOBJ);
return;
}
/*
* Count occurrences of an obj in a list.
*/
int count_obj_list(OBJ_INDEX_DATA * pObjIndex, OBJ_DATA * list)
{
OBJ_DATA *obj;
int nMatch = 0;
for (obj = list; obj; obj = obj->next_content)
{
if (obj->pIndexData->vnum == pObjIndex->vnum)
{
if (obj->count > 1)
nMatch += obj->count;
else
nMatch++;
}
}
return nMatch;
}
int count_mob_in_room(MOB_INDEX_DATA * pMobIndex, ROOM_INDEX_DATA * room)
{
CHAR_DATA *mob;
int nMatch = 0;
for (mob = room->first_person; mob; mob = mob->next_in_room)
if (IS_NPC(mob) && mob->pIndexData->vnum == pMobIndex->vnum)
nMatch++;
return nMatch;
}
/*
* Move an obj out of a room.
*/
void write_corpses args((CHAR_DATA * ch, char *name, OBJ_DATA * objrem));
int falling;
void obj_from_room(OBJ_DATA * obj)
{
ROOM_INDEX_DATA *in_room;
AFFECT_DATA *paf;
OMAP_DATA *omap;
if ((in_room = obj->in_room) == NULL)
{
bug("obj_from_room: NULL.", 0);
return;
}
for (paf = obj->first_affect; paf; paf = paf->next)
room_affect(in_room, paf, FALSE);
for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
room_affect(in_room, paf, FALSE);
if (obj->pIndexData->vnum != OBJ_VNUM_MONEY_ONE && obj->pIndexData->vnum != OBJ_VNUM_MONEY_SOME)
{
for (omap = first_wilderobj; omap; omap = omap->next)
{
if (omap->mapobj == obj)
UNLINK(omap, first_wilderobj, last_wilderobj, next, prev);
}
}
UNLINK(obj, in_room->first_content, in_room->last_content, next_content, prev_content);
/* uncover contents */
if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
empty_obj(obj, NULL, obj->in_room);
if (obj->item_type == ITEM_FIRE)
obj->in_room->light -= obj->count;
check_time_resets(obj);
obj->carried_by = NULL;
obj->possessed_by = NULL;
obj->in_obj = NULL;
obj->in_room = NULL;
if (obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1)
write_corpses(NULL, obj->short_descr + 14, obj);
return;
}
/*
* Move an obj into a room.
*/
OBJ_DATA *obj_to_room(OBJ_DATA * obj, ROOM_INDEX_DATA * pRoomIndex, CHAR_DATA * ch)
{
OBJ_DATA *otmp, *oret;
sh_int count = obj->count;
sh_int item_type = obj->item_type;
AFFECT_DATA *paf;
OMAP_DATA *omap;
if (IS_OBJ_STAT(obj, ITEM_GROUNDROT))
{
xREMOVE_BIT(obj->extra_flags, ITEM_GROUNDROT);
obj->timer = 1;
}
for (paf = obj->first_affect; paf; paf = paf->next)
room_affect(pRoomIndex, paf, TRUE);
for (paf = obj->pIndexData->first_affect; paf; paf = paf->next)
room_affect(pRoomIndex, paf, TRUE);
for (otmp = pRoomIndex->first_content; otmp; otmp = otmp->next_content)
if ((oret = group_object(otmp, obj)) == otmp)
{
if (item_type == ITEM_FIRE)
pRoomIndex->light += count;
return oret;
}
LINK(obj, pRoomIndex->first_content, pRoomIndex->last_content, next_content, prev_content);
if (obj->pIndexData->vnum != OBJ_VNUM_MONEY_ONE && obj->pIndexData->vnum != OBJ_VNUM_MONEY_SOME &&
pRoomIndex->vnum == OVERLAND_SOLAN)
{
CREATE(omap, OMAP_DATA, 1);
omap->mapobj = obj;
LINK(omap, first_wilderobj, last_wilderobj, next, prev);
}
obj->in_room = pRoomIndex;
obj->carried_by = NULL;
obj->in_obj = NULL;
if (item_type == ITEM_FIRE)
pRoomIndex->light += count;
falling++;
obj_fall(obj, FALSE);
falling--;
/* Hoping that this will cover all instances of objects from character to room - Samson 8-22-99 */
if (ch != NULL)
{
if (IN_WILDERNESS(ch))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = ch->map;
obj->coord->x = ch->coord->x;
obj->coord->y = ch->coord->y;
}
else
{
REMOVE_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = -1;
obj->coord->x = -1;
obj->coord->y = -1;
}
}
if (obj->pIndexData->vnum == OBJ_VNUM_CORPSE_PC && falling < 1)
write_corpses(NULL, obj->short_descr + 14, NULL);
return obj;
}
/*
* Who's carrying an item -- recursive for nested objects -Thoric
*/
CHAR_DATA *carried_by(OBJ_DATA * obj)
{
if (obj->in_obj)
return carried_by(obj->in_obj);
return obj->carried_by;
}
/*
* Move an object into an object.
*/
OBJ_DATA *obj_to_obj(OBJ_DATA * obj, OBJ_DATA * obj_to)
{
OBJ_DATA *otmp, *oret;
if (obj == obj_to)
{
bug("Obj_to_obj: trying to put object inside itself: vnum %d", obj->pIndexData->vnum);
return obj;
}
for (otmp = obj_to->first_content; otmp; otmp = otmp->next_content)
if ((oret = group_object(otmp, obj)) == otmp)
return oret;
LINK(obj, obj_to->first_content, obj_to->last_content, next_content, prev_content);
obj->in_obj = obj_to;
obj->in_room = NULL;
obj->carried_by = NULL;
/* This will hopefully cover all objs going into containers on maps - Samson 8-22-99 */
if (IN_WILDERNESS_OBJ(obj_to))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = obj_to->map;
obj->coord->x = obj_to->coord->x;
obj->coord->y = obj_to->coord->y;
}
return obj;
}
/*
* Move an object out of an object.
*/
void obj_from_obj(OBJ_DATA * obj)
{
OBJ_DATA *obj_from;
bool magic;
if ((obj_from = obj->in_obj) == NULL)
{
bug("Obj_from_obj: null obj_from.", 0);
return;
}
magic = in_magic_container(obj_from);
UNLINK(obj, obj_from->first_content, obj_from->last_content, next_content, prev_content);
/* uncover contents */
if (IS_OBJ_STAT(obj, ITEM_COVERING) && obj->first_content)
empty_obj(obj, obj->in_obj, NULL);
check_time_resets(obj);
obj->in_obj = NULL;
obj->in_room = NULL;
obj->carried_by = NULL;
/* This will hopefully cover all objs coming from containers going to the maps - Samson 8-22-99 */
if (IN_WILDERNESS_OBJ(obj_from))
{
SET_OBJ_STAT(obj, ITEM_ONMAP);
obj->map = obj_from->map;
obj->coord->x = obj_from->coord->x;
obj->coord->y = obj_from->coord->y;
}
return;
}
/*
* Extract an obj from the world.
*/
void extract_obj(OBJ_DATA * obj)
{
OBJ_DATA *obj_content;
DESCRIPTOR_DATA *d;
if (obj_extracted(obj))
{
bug("extract_obj: obj %d already extracted!", obj->pIndexData->vnum);
return;
}
if (obj->item_type == ITEM_PORTAL)
remove_portal(obj);
if (obj->carried_by)
obj_from_char(obj);
else if (obj->in_room)
obj_from_room(obj);
else if (obj->in_obj)
obj_from_obj(obj);
while ((obj_content = obj->last_content) != NULL)
extract_obj(obj_content);
/* remove affects */
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
for (paf = obj->first_affect; paf; paf = paf_next)
{
paf_next = paf->next;
DISPOSE(paf);
}
obj->first_affect = obj->last_affect = NULL;
}
// Remove traps
if (obj->trap)
{
if (obj->trap->uid >= START_INV_TRAP)
{
UNLINK(obj->trap, first_trap, last_trap, next, prev);
DISPOSE(obj->trap);
obj->trap = NULL;
save_trap_file(NULL, NULL);
}
else
{
obj->trap->area = NULL;
obj->trap->obj = NULL;
obj->trap = NULL;
}
}
/* remove extra descriptions */
{
EXTRA_DESCR_DATA *ed;
EXTRA_DESCR_DATA *ed_next;
for (ed = obj->first_extradesc; ed; ed = ed_next)
{
ed_next = ed->next;
STRFREE(ed->description);
STRFREE(ed->keyword);
DISPOSE(ed);
}
obj->first_extradesc = obj->last_extradesc = NULL;
}
if (obj == gobj_prev)
gobj_prev = obj->prev;
for (d = first_descriptor; d; d = d->next)
{
OBJ_DATA *dobj;
if (d->character && d->character->substate && d->character->dest_buf)
{
dobj = d->character->dest_buf;
if ((d->character->substate == SUB_RESTRICTED || d->character->substate == SUB_REPEATCMD)
&& dobj == obj)
{
send_to_char("Your obj you are modifying is being deleted, please type done to get out of this mode.\n\r", d->character);
d->character->substate = SUB_NONE;
d->character->dest_buf = NULL;
if (d->character->pcdata && d->character->pcdata->subprompt)
{
STRFREE(d->character->pcdata->subprompt);
d->character->pcdata->subprompt = NULL;
if (xIS_SET(d->character->act, PLR_OSET)) /* oset flags, Crash no like -- Xerves */
xREMOVE_BIT(d->character->act, PLR_OSET);
}
}
}
}
UNLINK(obj, first_object, last_object, next, prev);
/* shove onto extraction queue */
queue_extracted_obj(obj);
obj->pIndexData->count -= obj->count;
numobjsloaded -= obj->count;
--physicalobjects;
if (obj->serial == cur_obj)
{
cur_obj_extracted = TRUE;
if (global_objcode == rNONE)
global_objcode = rOBJ_EXTRACTED;
}
return;
}
void check_aff_learn(CHAR_DATA *ch, char *skillname, int sn, CHAR_DATA *victim, int success)
{
if (IS_NPC(ch))
return;
if (sn < 1)
sn = skill_lookup(skillname);
if (sn < 1)
return;
if (LEARNED(ch, sn) <= 0)
return;
if (success)
learn_from_success(ch, sn, victim);
else
learn_from_failure(ch, sn, victim);
return;
}
bool check_npc(CHAR_DATA *ch)
{
if (IS_NPC(ch))
{
send_to_char("This is not for a NPC to use.\n\r", ch);
return TRUE;
}
return FALSE;
}
/*
* Extract a char from the world.
*/
void extract_char(CHAR_DATA * ch, bool fPull)
{
CHAR_DATA *wch;
OBJ_DATA *obj;
char buf[MSL];
ROOM_INDEX_DATA *location;
AREA_DATA *pArea;
TOWN_DATA *town;
AGGRO_DATA *aggro;
AGGRO_DATA *naggro;
if (!ch)
{
bug("Extract_char: NULL ch.", 0);
return;
}
if (!ch->in_room)
{
bug("Extract_char: %s in NULL room.", ch->name ? ch->name : "???");
return;
}
if (ch == supermob)
{
bug("Extract_char: ch == supermob!", 0);
return;
}
if (char_died(ch))
{
bug("extract_char: %s already died!", ch->name);
return;
}
if (ch == cur_char)
cur_char_died = TRUE;
/* shove onto extraction queue */
queue_extracted_char(ch, fPull);
if (gch_prev == ch)
gch_prev = ch->prev;
/* DELETE LATER SHADDAI
if ( fPull && !xIS_SET(ch->act, ACT_POLYMORPHED))
*/
if (fPull)
die_follower(ch);
stop_fighting(ch, TRUE);
pArea = ch->in_room->area;
if (xIS_SET(ch->in_room->room_flags, ROOM_ARENA))
{
ch->hit = ch->max_hit;
ch->mana = ch->max_mana;
ch->move = ch->max_move;
}
if (ch->rider)
{
act(AT_SOCIAL, "Since you are leaving it is a good time for $N to get off of you", ch, NULL, ch->rider, TO_CHAR);
act(AT_SOCIAL, "$n is leaving, time for your free ride to stop.", ch, NULL, ch->rider, TO_VICT);
act(AT_PLAIN, "$n is leaving, sadly $N must hop off of $s back.", ch, NULL, ch->rider, TO_ROOM);
ch->rider->position = POS_STANDING;
ch->rider->riding = NULL;
ch->rider = NULL;
}
if (ch->riding)
{
act(AT_SOCIAL, "You hop off the back of $N before taking your leave.", ch, NULL, ch->riding, TO_CHAR);
act(AT_SOCIAL, "$n hops off the back of $N before leaving.", ch, NULL, ch->riding, TO_VICT);
act(AT_PLAIN, "$n hops off the back of $N before departing.", ch, NULL, ch->riding, TO_ROOM);
ch->rider->riding = NULL;
ch->rider = NULL;
ch->position = POS_STANDING;
}
if (ch->mount)
{
xREMOVE_BIT(ch->mount->act, ACT_MOUNTED);
ch->mount = NULL;
ch->position = POS_STANDING;
}
if (IS_NPC(ch))
{
if (xIS_SET(ch->act, ACT_MILITARY))
{
bug("%s of kingdom %s is being extracted.", ch->name, kingdom_table[ch->m4]->name);
town = get_town_tpid(ch->m4, ch->m1);
if (town)
{
write_kingdom_file(ch->m4);
}
}
if (xIS_SET(ch->act, ACT_EXTRACTMOB))
{
bug("%s of kingdom %s is being extracted.", ch->name, kingdom_table[ch->m4]->name);
town = get_town_tpid(ch->m4, ch->m7);
if (town)
{
write_kingdom_file(ch->m4);
}
}
}
/*
* check if this NPC was a mount or a pet
*/
if (IS_NPC(ch))
{
for (wch = first_char; wch; wch = wch->next)
{
if (wch->mount == ch)
{
wch->mount = NULL;
wch->position = POS_STANDING;
if (wch->in_room == ch->in_room && saving_mount_on_quit == 0)
{
act(AT_SOCIAL, "Your faithful mount, $N collapses beneath you...", wch, NULL, ch, TO_CHAR);
act(AT_SOCIAL, "Sadly you dismount $M for the last time.", wch, NULL, ch, TO_CHAR);
act(AT_PLAIN, "$n sadly dismounts $N for the last time.", wch, NULL, ch, TO_ROOM);
}
}
if (wch->pcdata && wch->pcdata->pet == ch)
{
wch->pcdata->pet = NULL;
if (wch->in_room == ch->in_room)
act(AT_SOCIAL, "You mourn for the loss of $N.", wch, NULL, ch, TO_CHAR);
}
if (wch->pcdata && wch->pcdata->mount == ch)
{
wch->pcdata->mount = NULL;
if (wch->in_room == ch->in_room && saving_mount_on_quit == 0)
act(AT_SOCIAL, "You mourn for the loss of $N, but it had to be....", wch, NULL, ch, TO_CHAR);
}
if (wch->pcdata && wch->pcdata->aimtarget == ch)
wch->pcdata->aimtarget = NULL;
}
}
xREMOVE_BIT(ch->act, ACT_MOUNTED);
while ((obj = ch->last_carrying) != NULL)
extract_obj(obj);
if (fPull)
char_from_room(ch);
if (!fPull)
{
location = NULL;
if (!IS_NPC(ch) && ch->pcdata->clan)
location = get_room_index(ch->pcdata->clan->recall);
if (!IS_NPC(ch) && ch->pcdata->caste < 2)
location = get_room_index(5644);
if (!location && !IS_NPC(ch) && ch->pcdata->town)
location = get_room_index(OVERLAND_SOLAN);
if (!location)
location = get_room_index(ROOM_VNUM_ALTAR);
if (!location)
location = get_room_index(1);
if (IS_ONMAP_FLAG(ch))
{
REMOVE_ONMAP_FLAG(ch);
REMOVE_PLR_FLAG(ch, PLR_MAPEDIT); /* Just in case they were editing */
ch->coord->x = -1;
ch->coord->y = -1;
ch->map = -1;
}
if (ch->pcdata->mount)
{
char_from_room(ch->pcdata->mount);
SET_ONMAP_FLAG(ch->pcdata->mount);
ch->pcdata->mount->coord->x = -1;
ch->pcdata->mount->coord->y = -1;
ch->pcdata->mount->map = -1;
char_to_room(ch->pcdata->mount, location);
ch->pcdata->mount->position = POS_STANDING;
}
char_from_room(ch);
char_to_room(ch, location);
if (location->vnum == OVERLAND_SOLAN)
{
ch->coord->x = ch->pcdata->town->death[0];
ch->coord->y = ch->pcdata->town->death[1];
ch->map = ch->pcdata->town->death[2];
SET_ONMAP_FLAG(ch);
if (ch->pcdata->mount)
{
SET_ONMAP_FLAG(ch->pcdata->mount);
ch->pcdata->mount->coord->x = ch->coord->x;
ch->pcdata->mount->coord->y = ch->coord->y;
ch->pcdata->mount->map = ch->map;
}
}
update_objects(ch, ch->map, ch->coord->x, ch->coord->y);
/*
* Make things a little fancier -Thoric
*/
if ((wch = get_char_room_new(ch, "healer", 1)) != NULL)
{
act(AT_MAGIC, "$n mutters a few incantations, waves $s hands and points $s finger.", wch, NULL, NULL, TO_ROOM);
act(AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM);
sprintf(buf, "Welcome back to the land of the living, %s", capitalize(ch->name));
do_tell(wch, buf);
}
else
act(AT_MAGIC, "$n appears from some strange swirling mists!", ch, NULL, NULL, TO_ROOM);
ch->position = POS_RESTING;
return;
}
if (!IS_NPC(ch))
{
while ((obj = ch->pcdata->last_bankobj) != NULL)
{
bank_to_char(obj, ch);
extract_obj(obj);
}
}
if (IS_NPC(ch))
{
RESET_DATA *pReset;
DESCRIPTOR_DATA *d;
for (d = first_descriptor; d; d = d->next)
{
CHAR_DATA *dch;
if (d->character && d->character->substate && d->character->dest_buf)
{
dch = d->character->dest_buf;
if ((d->character->substate == SUB_RESTRICTED || d->character->substate == SUB_REPEATCMD)
&& dch == ch)
{
send_to_char("The mobile you are modifying is being deleted, please type done to get out of this mode.\n\r", d->character);
d->character->substate = SUB_NONE;
d->character->dest_buf = NULL;
if (d->character->pcdata && d->character->pcdata->subprompt)
{
STRFREE(d->character->pcdata->subprompt);
d->character->pcdata->subprompt = NULL;
if (xIS_SET(d->character->act, PLR_MSET)) /* oset flags, Crash no like -- Xerves */
xREMOVE_BIT(d->character->act, PLR_MSET);
}
}
}
}
--ch->pIndexData->count;
--nummobsloaded;
if (xIS_SET(ch->act, ACT_NORESET)) //remove the reset....
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->command == 'M' && pReset->serial == ch->serial)
break;
}
if (!pReset)
{
bug("Mobile %d in Area %s cannot find the proper reset to remove itself (No reset mob)", ch->pIndexData->vnum, pArea->name);
}
else
{
delete_reset(pArea, pReset);
fold_area(pArea, pArea->filename, FALSE, 1);
}
}
if (xIS_SET(ch->act, ACT_TIMERESET)) //adjust the looted bit
{
for (pReset = pArea->first_reset; pReset; pReset = pReset->next)
{
if (pReset->command == 'M' && pReset->serial == ch->serial)
break;
}
if (!pReset)
{
bug("Mobile %d in Area %s cannot find the proper reset to remove itself (No reset mob)", ch->pIndexData->vnum, pArea->name);
}
else
{
pReset->resetlast = time(0);
fold_area(pArea, pArea->filename, FALSE, 1);
}
}
serial_list[ch->serial] = FALSE;
}
/* Not sure this should stay or not Shaddai */
/*
if ( ch->morph )
do_unmorph( ch );
*/
if (ch->desc && ch->desc->original)
do_return(ch, "");
for (aggro = first_global_aggro; aggro; aggro = naggro)
{
naggro = aggro->next_global;
if (aggro->ch == ch)
{
UNLINK(aggro, first_global_aggro, last_global_aggro, next_global, prev_global);
UNLINK(aggro, aggro->owner->first_aggro, aggro->owner->last_aggro, next, prev);
DISPOSE(aggro);
}
}
for (wch = first_char; wch; wch = wch->next)
{
if (wch->reply == ch)
wch->reply = NULL;
if (wch->retell == ch)
wch->retell = NULL;
}
/*
if (IS_NPC(ch))
{
for (mch = first_wilderchar; mch; mch = mch->next)
{
if (mch->mapch->coord->x == ch->coord->x && mch->mapch->coord->y == ch->coord->y && mch->mapch->map == ch->map)
{
UNLINK( mch, first_wilderchar, last_wilderchar, next, prev );
top_map_mob--;
}
}
} */
UNLINK(ch, first_char, last_char, next, prev);
if (ch->desc)
{
if (ch->desc->character != ch)
bug("Extract_char: char's descriptor points to another char", 0);
else
{
ch->desc->character = NULL;
close_socket(ch->desc, FALSE);
ch->desc = NULL;
}
}
return;
}
/*
* Find a char in the room.
*/
//use get_char_room unless you need to call get_char_room_new for the type (wilderness check)
CHAR_DATA *get_char_room_new(CHAR_DATA * ch, char *argument, int type)
{
char arg[MIL];
CHAR_DATA *rch;
int number, count, vnum;
number = number_argument(argument, arg);
if (!str_cmp(arg, "self"))
return ch;
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
count = 0;
for (rch = ch->in_room->first_person; rch; rch = rch->next_in_room)
if (can_see_map(ch, rch) && (nifty_is_name(arg, PERS_MAP_NAME(rch, ch)) || (IS_NPC(rch) && vnum == rch->pIndexData->vnum)))
{
if (type == 1)
{
if (IS_ONMAP_FLAG(ch) && IS_ONMAP_FLAG(rch))
{
if (ch->map != rch->map || ch->coord->x != rch->coord->x || ch->coord->y != rch->coord->y)
continue;
}
}
if (number == 0 && !IS_NPC(rch))
return rch;
else if (++count == number)
return rch;
}
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, run through the list of characters
* again looking for prefix matching, ie gu == guard.
* Added by Narn, Sept/96
*/
count = 0;
for (rch = ch->in_room->first_person; rch; rch = rch->next_in_room)
{
if (!can_see_map(ch, rch) || !nifty_is_name_prefix(arg, PERS_MAP_NAME(rch, ch)))
continue;
if (type == 1)
{
if (IS_ONMAP_FLAG(ch) && IS_ONMAP_FLAG(rch))
{
if (ch->map != rch->map || ch->coord->x != rch->coord->x || ch->coord->y != rch->coord->y)
continue;
}
}
if (number == 0 && !IS_NPC(rch))
return rch;
else if (++count == number)
return rch;
}
return NULL;
}
//Checks Wilderness by default now
CHAR_DATA *get_char_room(CHAR_DATA * ch, char *argument)
{
return get_char_room_new(ch, argument, 1);
}
CHAR_DATA *get_char_wilder(CHAR_DATA * ch, char *argument)
{
return get_char_room_new(ch, argument, -1);
}
/*
* Find a char in the world.
*/
CHAR_DATA *get_char_world(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
CHAR_DATA *wch;
int number, count, vnum;
number = number_argument(argument, arg);
count = 0;
if (!str_cmp(arg, "self"))
return ch;
/*
* Allow reference by vnum for saints+ -Thoric
*/
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
/* check the room for an exact match */
for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room)
if (can_see_map(ch, wch) && (nifty_is_name(arg, PERS_MAP_NAME(wch, ch)) || (IS_NPC(wch) && vnum == wch->pIndexData->vnum)))
{
if (number == 0 && !IS_NPC(wch))
return wch;
else if (++count == number)
return wch;
}
count = 0;
/* check the world for an exact match */
for (wch = first_char; wch; wch = wch->next)
if (can_see_map(ch, wch) && (nifty_is_name(arg, PERS_MAP_NAME(wch, ch)) || (IS_NPC(wch) && vnum == wch->pIndexData->vnum)))
{
if (number == 0 && !IS_NPC(wch))
return wch;
else if (++count == number)
return wch;
}
/* bail out if looking for a vnum match */
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, check the room for
* for a prefix match, ie gu == guard.
* Added by Narn, Sept/96
*/
count = 0;
for (wch = ch->in_room->first_person; wch; wch = wch->next_in_room)
{
if (!can_see_map(ch, wch) || !nifty_is_name_prefix(arg, PERS_MAP_NAME(wch, ch)))
continue;
if (number == 0 && !IS_NPC(wch))
return wch;
else if (++count == number)
return wch;
}
/*
* If we didn't find a prefix match in the room, run through the full list
* of characters looking for prefix matching, ie gu == guard.
* Added by Narn, Sept/96
*/
count = 0;
for (wch = first_char; wch; wch = wch->next)
{
if (!can_see_map(ch, wch) || !nifty_is_name_prefix(arg, PERS_MAP_NAME(wch, ch)))
continue;
if (number == 0 && !IS_NPC(wch))
return wch;
else if (++count == number)
return wch;
}
return NULL;
}
/*
* Find some object with a given index data.
* Used by area-reset 'P', 'T' and 'H' commands.
*/
OBJ_DATA *get_obj_type(OBJ_INDEX_DATA * pObjIndex)
{
OBJ_DATA *obj;
for (obj = last_object; obj; obj = obj->prev)
if (obj->pIndexData == pObjIndex)
return obj;
return NULL;
}
/*
* Find an obj in a list.
*/
OBJ_DATA *get_obj_list(CHAR_DATA * ch, char *argument, OBJ_DATA * list)
{
char arg[MIL];
OBJ_DATA *obj;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
for (obj = list; obj; obj = obj->next_content)
if (can_see_obj(ch, obj) && nifty_is_name(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = list; obj; obj = obj->next_content)
if (can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
return NULL;
}
/*
* Find an obj in a list...going the other way -Thoric
*/
OBJ_DATA *get_obj_list_rev(CHAR_DATA * ch, char *argument, OBJ_DATA * list)
{
char arg[MIL];
OBJ_DATA *obj;
int number;
int count;
number = number_argument(argument, arg);
count = 0;
for (obj = list; obj; obj = obj->prev_content)
if (can_see_obj(ch, obj) && nifty_is_name(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = list; obj; obj = obj->prev_content)
if (can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
return NULL;
}
/*
* Find an obj in player's inventory or wearing via a vnum -Shaddai
*/
OBJ_DATA *get_obj_vnum(CHAR_DATA * ch, int vnum)
{
OBJ_DATA *obj;
for (obj = ch->last_carrying; obj; obj = obj->prev_content)
if (can_see_obj(ch, obj) && obj->pIndexData->vnum == vnum)
return obj;
return NULL;
}
/*
* Find an obj in player's inventory.
*/
OBJ_DATA *get_obj_carry(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
int number, count, vnum;
number = number_argument(argument, arg);
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
count = 0;
for (obj = ch->last_carrying; obj; obj = obj->prev_content)
if (obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && (nifty_is_name(arg, obj->name) || obj->pIndexData->vnum == vnum))
if ((count += obj->count) >= number)
return obj;
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = ch->last_carrying; obj; obj = obj->prev_content)
if (obj->wear_loc == WEAR_NONE && can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
return NULL;
}
/*
* Find an obj in player's equipment.
*/
OBJ_DATA *get_obj_wear(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
int number, count, vnum;
number = number_argument(argument, arg);
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
count = 0;
for (obj = ch->last_carrying; obj; obj = obj->prev_content)
if (obj->wear_loc != WEAR_NONE && can_see_obj(ch, obj) && (nifty_is_name(arg, obj->name) || obj->pIndexData->vnum == vnum))
if (++count == number)
return obj;
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = ch->last_carrying; obj; obj = obj->prev_content)
if (obj->wear_loc != WEAR_NONE && can_see_obj(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if (++count == number)
return obj;
return NULL;
}
/*
* Find an obj in the room or in inventory.
*/
OBJ_DATA *get_obj_here(CHAR_DATA * ch, char *argument)
{
OBJ_DATA *obj;
obj = get_obj_list_rev(ch, argument, ch->in_room->last_content);
if (obj)
return obj;
if ((obj = get_obj_carry(ch, argument)) != NULL)
return obj;
if ((obj = get_obj_wear(ch, argument)) != NULL)
return obj;
return NULL;
}
/*
* Find an obj in the world.
*/
OBJ_DATA *get_obj_world(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
int number, count, vnum;
if ((obj = get_obj_here(ch, argument)) != NULL)
return obj;
number = number_argument(argument, arg);
/*
* Allow reference by vnum for saints+ -Thoric
*/
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
count = 0;
for (obj = first_object; obj; obj = obj->next)
if (can_see_obj_map(ch, obj) && (nifty_is_name(arg, obj->name) || vnum == obj->pIndexData->vnum))
if ((count += obj->count) >= number)
return obj;
/* bail out if looking for a vnum */
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = first_object; obj; obj = obj->next)
if (can_see_obj_map(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if ((count += obj->count) >= number)
return obj;
return NULL;
}
/*
* Find an obj only if it is on a mob...
*/
OBJ_DATA *get_obj_mobworld(CHAR_DATA * ch, char *argument)
{
char arg[MIL];
OBJ_DATA *obj;
OBJ_DATA *mobj; /* Check to see if item is same as in inv */
int number, count, vnum;
if ((obj = get_obj_here(ch, argument)) != NULL)
mobj = obj;
else
mobj = NULL;
number = number_argument(argument, arg);
/*
* Allow reference by vnum for saints+ -Thoric
*/
if (get_trust(ch) >= LEVEL_IMM && is_number(arg)) /* Tracker1 */
vnum = atoi(arg);
else
vnum = -1;
count = 0;
for (obj = first_object; obj; obj = obj->next)
{
if (can_see_obj_map(ch, obj) && (nifty_is_name(arg, obj->name) || vnum == obj->pIndexData->vnum))
if ((count += obj->count) >= number)
if ((obj->carried_by != NULL) && (mobj != NULL))
{
if ((IS_NPC(obj->carried_by)) && (obj->name == mobj->name) && (obj->pIndexData->vnum > 99))
return obj;
}
}
/* bail out if looking for a vnum */
if (vnum != -1)
return NULL;
/*
* If we didn't find an exact match, run through the list of objects
* again looking for prefix matching, ie swo == sword.
* Added by Narn, Sept/96
*/
count = 0;
for (obj = first_object; obj; obj = obj->next)
{
if (can_see_obj_map(ch, obj) && nifty_is_name_prefix(arg, obj->name))
if ((count += obj->count) >= number)
if ((obj->carried_by != NULL) && (mobj != NULL))
{
if ((IS_NPC(obj->carried_by)) && (obj->name == mobj->name) && (obj->pIndexData->vnum > 99))
return obj;
}
}
return NULL;
}
/*
* How mental state could affect finding an object -Thoric
* Used by get/drop/put/quaff/recite/etc
* Increasingly freaky based on mental state and drunkeness
*/
bool ms_find_obj(CHAR_DATA * ch)
{
int ms = ch->mental_state;
int drunk = IS_NPC(ch) ? 0 : ch->pcdata->condition[COND_DRUNK];
char *t;
/*
* we're going to be nice and let nothing weird happen unless
* you're a tad messed up
*/
drunk = UMAX(1, drunk);
if (abs(ms) + (drunk / 3) < 30)
return FALSE;
if ((number_percent() + (ms < 0 ? 15 : 5)) > abs(ms) / 2 + drunk / 4)
return FALSE;
if (ms > 15) /* range 1 to 20 -- feel free to add more */
switch (number_range(UMAX(1, (ms / 5 - 15)), (ms + 4) / 5))
{
default:
case 1:
t = "As you reach for it, you forgot what it was...\n\r";
break;
case 2:
t = "As you reach for it, something inside stops you...\n\r";
break;
case 3:
t = "As you reach for it, it seems to move out of the way...\n\r";
break;
case 4:
t = "You grab frantically for it, but can't seem to get a hold of it...\n\r";
break;
case 5:
t = "It disappears as soon as you touch it!\n\r";
break;
case 6:
t = "You would if it would stay still!\n\r";
break;
case 7:
t = "Whoa! It's covered in blood! Ack! Ick!\n\r";
break;
case 8:
t = "Wow... trails!\n\r";
break;
case 9:
t = "You reach for it, then notice the back of your hand is growing something!\n\r";
break;
case 10:
t = "As you grasp it, it shatters into tiny shards which bite into your flesh!\n\r";
break;
case 11:
t = "What about that huge dragon flying over your head?!?!?\n\r";
break;
case 12:
t = "You stratch yourself instead...\n\r";
break;
case 13:
t = "You hold the universe in the palm of your hand!\n\r";
break;
case 14:
t = "You're too scared.\n\r";
break;
case 15:
t = "Your mother smacks your hand... 'NO!'\n\r";
break;
case 16:
t = "Your hand grasps the worst pile of revoltingness that you could ever imagine!\n\r";
break;
case 17:
t = "You stop reaching for it as it screams out at you in pain!\n\r";
break;
case 18:
t = "What about the millions of burrow-maggots feasting on your arm?!?!\n\r";
break;
case 19:
t = "That doesn't matter anymore... you've found the true answer to everything!\n\r";
break;
case 20:
t = "A supreme entity has no need for that.\n\r";
break;
}
else
{
int sub = URANGE(1, abs(ms) / 2 + drunk, 60);
switch (number_range(1, sub / 10))
{
default:
case 1:
t = "In just a second...\n\r";
break;
case 2:
t = "You can't find that...\n\r";
break;
case 3:
t = "It's just beyond your grasp...\n\r";
break;
case 4:
t = "...but it's under a pile of other stuff...\n\r";
break;
case 5:
t = "You go to reach for it, but pick your nose instead.\n\r";
break;
case 6:
t = "Which one?!? I see two... no three...\n\r";
break;
}
}
send_to_char(t, ch);
return TRUE;
}
/*
* Generic get obj function that supports optional containers. -Thoric
* currently only used for "eat" and "quaff".
*/
OBJ_DATA *find_obj(CHAR_DATA * ch, char *argument, bool carryonly)
{
char arg1[MIL];
char arg2[MIL];
OBJ_DATA *obj = NULL;
argument = one_argument(argument, arg1);
argument = one_argument(argument, arg2);
if (!str_cmp(arg2, "from") && argument[0] != '\0')
argument = one_argument(argument, arg2);
if (arg2[0] == '\0')
{
if (carryonly && (obj = get_obj_carry(ch, arg1)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return NULL;
}
else if (!carryonly && (obj = get_obj_here(ch, arg1)) == NULL)
{
act(AT_PLAIN, "I see no $T here.", ch, NULL, arg1, TO_CHAR);
return NULL;
}
return obj;
}
else
{
OBJ_DATA *container = NULL;
if (carryonly && (container = get_obj_carry(ch, arg2)) == NULL && (container = get_obj_wear(ch, arg2)) == NULL)
{
send_to_char("You do not have that item.\n\r", ch);
return NULL;
}
if (!carryonly && (container = get_obj_here(ch, arg2)) == NULL)
{
act(AT_PLAIN, "I see no $T here.", ch, NULL, arg2, TO_CHAR);
return NULL;
}
if (!IS_OBJ_STAT(container, ITEM_COVERING) && IS_SET(container->value[1], CONT_CLOSED))
{
act(AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR);
return NULL;
}
obj = get_obj_list(ch, arg1, container->first_content);
if (!obj)
act(AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ?
"I see nothing like that beneath $p." : "I see nothing like that in $p.", ch, container, NULL, TO_CHAR);
return obj;
}
return NULL;
}
int get_obj_number(OBJ_DATA * obj)
{
return obj->count;
}
/*
* Return TRUE if an object is, or nested inside a magic container
*/
bool in_magic_container(OBJ_DATA * obj)
{
if (obj->item_type == ITEM_CONTAINER && IS_OBJ_STAT(obj, ITEM_MAGIC))
return TRUE;
if (obj->in_obj)
return in_magic_container(obj->in_obj);
return FALSE;
}
int objonchar;
void search_container_for_obj(OBJ_DATA * obj, OBJ_DATA * pobj)
{
OBJ_DATA *cobj;
for (cobj = obj->first_content; cobj; cobj = cobj->next_content)
{
if (objonchar == 1)
break;
if ((cobj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum != OBJ_VNUM_QUESTOBJ)
|| (cobj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum == OBJ_VNUM_QUESTOBJ
&& !str_cmp(cobj->name, pobj->name)))
{
objonchar = 1;
break;
}
if (cobj->first_content)
search_container_for_obj(cobj, pobj);
}
}
int get_obj_on_char(CHAR_DATA *ch, OBJ_DATA * pobj)
{
OBJ_DATA *obj;
objonchar = 0;
if (IS_NPC(ch))
return 0;
if (xIS_SET(pobj->extra_flags, ITEM_UNIQUE))
{
for (obj = ch->first_carrying; obj; obj = obj->next_content)
{
if (objonchar == 1)
break;
if ((obj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum != OBJ_VNUM_QUESTOBJ)
|| (obj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum == OBJ_VNUM_QUESTOBJ
&& !str_cmp(obj->name, pobj->name)))
{
objonchar = 1;
break;
}
if (obj->first_content)
search_container_for_obj(obj, pobj);
}
for (obj = ch->pcdata->first_bankobj; obj; obj = obj->next_content)
{
if (objonchar == 1)
break;
if ((obj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum != OBJ_VNUM_QUESTOBJ)
|| (obj->pIndexData->vnum == pobj->pIndexData->vnum && pobj->pIndexData->vnum == OBJ_VNUM_QUESTOBJ
&& !str_cmp(obj->name, pobj->name)))
{
objonchar = 1;
break;
}
if (obj->first_content)
search_container_for_obj(obj, pobj);
}
}
if (pobj->first_content)
{
for (obj = pobj->first_content; obj; obj = obj->next_content)
{
if (objonchar == 1)
break;
if (IS_UNIQUE(ch, obj))
objonchar = 1;
}
}
return objonchar;
}
/*
* Return weight of an object, including weight of contents (unless magic).
*/
float get_obj_weight(OBJ_DATA * obj)
{
float weight;
float reduction = 100;
CHAR_DATA *ch = obj->carried_by;
weight = (float)obj->count * obj->weight;
if (obj->item_type == ITEM_CONTAINER)
{
if (ch && ch->apply_wmod > 0)
reduction = reduction * URANGE(30, (float)ch->apply_wmod, 200) / 100;
weight = weight * reduction / 100;
if (obj->value[2] > 0)
reduction = (float)obj->value[2];
}
else
{
if (ch && ch->apply_wmod > 0)
reduction = reduction * URANGE(30, (float)ch->apply_wmod, 200) / 100;
weight = weight * reduction / 100;
}
/* magic containers */
for (obj = obj->first_content; obj; obj = obj->next_content)
weight += get_obj_weight(obj) * reduction / 100;
return weight;
}
/*
* Return real weight of an object, including weight of contents.
*/
int get_real_obj_weight(OBJ_DATA * obj)
{
int weight;
weight = obj->count * obj->weight;
for (obj = obj->first_content; obj; obj = obj->next_content)
weight += get_real_obj_weight(obj);
return weight;
}
/*
* True if room is dark.
*/
bool room_is_dark(ROOM_INDEX_DATA * pRoomIndex)
{
if (!pRoomIndex)
{
bug("room_is_dark: NULL pRoomIndex", 0);
return TRUE;
}
if (pRoomIndex->light > 0)
return FALSE;
if (xIS_SET(pRoomIndex->room_flags, ROOM_DARK))
return TRUE;
if (pRoomIndex->sector_type == SECT_INSIDE || pRoomIndex->sector_type == SECT_CITY || pRoomIndex->sector_type == SECT_ROAD)
return FALSE;
if (pRoomIndex->vnum == OVERLAND_SOLAN)
return FALSE;
if (pRoomIndex->sector_type == SECT_UNDERWATER || pRoomIndex->sector_type == SECT_OCEANFLOOR || pRoomIndex->sector_type == SECT_UNDERGROUND)
return TRUE;
if (time_info.sunlight == SUN_SET || time_info.sunlight == SUN_DARK)
return TRUE;
return FALSE;
}
//True if room is private for wilderness
bool room_is_private_wilderness(CHAR_DATA *ch, ROOM_INDEX_DATA *pRoomIndex, int x, int y, int map)
{
CHAR_DATA *rch;
int count;
int rvalue;
int oldx, oldy, oldmap;
ROOM_INDEX_DATA *oldroom;
if (!pRoomIndex)
{
bug("room_is_private: NULL pRoomIndex", 0);
return FALSE;
}
oldx = ch->coord->x;
oldy = ch->coord->y;
oldmap = ch->map;
oldroom = ch->in_room;
ch->coord->x = x;
ch->coord->y = y;
ch->map = map;
ch->in_room = pRoomIndex;
if (ch->in_room->vnum == OVERLAND_SOLAN)
SET_ONMAP_FLAG(ch);
else
REMOVE_ONMAP_FLAG(ch);
if (!IN_WILDERNESS(ch))
{
ch->coord->x = oldx;
ch->coord->y = oldy;
ch->map = oldmap;
ch->in_room = oldroom;
if (ch->in_room->vnum == OVERLAND_SOLAN)
SET_ONMAP_FLAG(ch);
else
REMOVE_ONMAP_FLAG(ch);
return FALSE;
}
count = 0;
for (rch = pRoomIndex->first_person; rch; rch = rch->next_in_room)
{
if (rch->coord->x == x && rch->coord->y == y && rch->map == map)
count++;
}
if (wIS_SET(ch, ROOM_PRIVATE) && count >= 2)
rvalue = TRUE;
else if (wIS_SET(ch, ROOM_SOLITARY) && count >= 1)
rvalue = TRUE;
else
rvalue = FALSE;
ch->coord->x = oldx;
ch->coord->y = oldy;
ch->map = oldmap;
ch->in_room = oldroom;
if (ch->in_room->vnum == OVERLAND_SOLAN)
SET_ONMAP_FLAG(ch);
else
REMOVE_ONMAP_FLAG(ch);
return FALSE;
}
/*
* True if room is private.
*/
bool room_is_private(ROOM_INDEX_DATA * pRoomIndex)
{
CHAR_DATA *rch;
int count;
if (!pRoomIndex)
{
bug("room_is_private: NULL pRoomIndex", 0);
return FALSE;
}
count = 0;
for (rch = pRoomIndex->first_person; rch; rch = rch->next_in_room)
count++;
if (xIS_SET(pRoomIndex->room_flags, ROOM_PRIVATE) && count >= 2)
return TRUE;
if (xIS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) && count >= 1)
return TRUE;
return FALSE;
}
/*
* True if char can see victim.
*/
bool can_see(CHAR_DATA * ch, CHAR_DATA * victim)
{
if (!ch)
{
if (IS_AFFECTED(victim, AFF_INVISIBLE) || IS_AFFECTED(victim, AFF_STALK) || IS_AFFECTED(victim, AFF_HIDE) || xIS_SET(victim->act, PLR_WIZINVIS))
return FALSE;
else
return TRUE;
}
if (ch == victim)
return TRUE;
if (!IS_NPC(victim) && xIS_SET(victim->act, PLR_WIZINVIS) && get_trust(ch) < victim->pcdata->wizinvis)
return FALSE;
/* SB */
if (IS_NPC(victim) && xIS_SET(victim->act, ACT_MOBINVIS) && get_trust(ch) <= LEVEL_GUEST)
return FALSE;
if (!IS_NPC(victim))
{
if (!IS_NPC(ch))
{
if (IN_WILDERNESS(ch) || IN_WILDERNESS(victim))
{
if (ch->map != victim->map
|| ch->coord->x != victim->coord->x
|| ch->coord->y != victim->coord->y)
return FALSE;
}
}
else
{
if (IN_WILDERNESS(ch) || IN_WILDERNESS(victim))
{
if (ch->map != victim->map
|| ch->coord->x != victim->coord->x
|| ch->coord->y != victim->coord->y)
return FALSE;
}
}
}
else
{
if (!IS_NPC(ch))
{
if (IN_WILDERNESS(ch) || IN_WILDERNESS(victim))
{
if (ch->map != victim->map
|| ch->coord->x != victim->coord->x
|| ch->coord->y != victim->coord->y)
return FALSE;
}
}
else
{
if (IN_WILDERNESS(ch) || IN_WILDERNESS(victim))
{
if (ch->map != victim->map
|| ch->coord->x != victim->coord->x
|| ch->coord->y != victim->coord->y)
return FALSE;
}
}
}
if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
if (IS_AFFECTED(victim, AFF_STALK))
return FALSE;
/* The miracle cure for blindness? -- Altrag */
if (!IS_AFFECTED(ch, AFF_TRUESIGHT))
{
if (IS_AFFECTED(ch, AFF_BLIND))
return FALSE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_AFFECTED(victim, AFF_INVISIBLE) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
if (IS_AFFECTED(victim, AFF_HIDE)
&& !IS_AFFECTED(ch, AFF_DETECT_HIDDEN))
return FALSE;
}
/* Redone by Narn to let newbie council members see pre-auths. */
if (NOT_AUTHED(victim))
{
if (NOT_AUTHED(ch) || IS_IMMORTAL(ch) || IS_NPC(ch))
return TRUE;
if (ch->pcdata->council && !str_cmp(ch->pcdata->council->name, "Newbie Council"))
return TRUE;
return FALSE;
}
/* Commented out for who list purposes
if (!NOT_AUTHED(victim) && NOT_AUTHED(ch) && !IS_IMMORTAL(victim)
&& !IS_NPC(victim))
return FALSE;*/
return TRUE;
}
//Global can_see check, like below but used mob_index, don't want to load mobiles that aren't going to attack (etc)
bool can_see_index(MOB_INDEX_DATA *ch, CHAR_DATA *victim)
{
if (IS_NPC(victim) && ch == victim->pIndexData)
return TRUE;
if (!IS_NPC(victim) && xIS_SET(victim->act, PLR_WIZINVIS))
return FALSE;
/* SB */
if (IS_NPC(victim) && xIS_SET(victim->act, ACT_MOBINVIS))
return FALSE;
/* The miracle cure for blindness? -- Altrag */
if (!xIS_SET(ch->affected_by, AFF_TRUESIGHT))
{
if (xIS_SET(ch->affected_by, AFF_BLIND))
return FALSE;
if (IS_AFFECTED(victim, AFF_INVISIBLE) && !xIS_SET(ch->affected_by, AFF_DETECT_INVIS))
return FALSE;
if (IS_AFFECTED(victim, AFF_HIDE)
&& !xIS_SET(ch->affected_by, AFF_DETECT_HIDDEN))
return FALSE;
}
return TRUE;
}
/* Like can_see, but is used for global things like who */
bool can_see_map(CHAR_DATA * ch, CHAR_DATA * victim)
{
if (!ch)
{
if (IS_AFFECTED(victim, AFF_INVISIBLE) || IS_AFFECTED(victim, AFF_HIDE) || xIS_SET(victim->act, PLR_WIZINVIS))
return FALSE;
else
return TRUE;
}
if (ch == victim)
return TRUE;
if (!IS_NPC(victim) && xIS_SET(victim->act, PLR_WIZINVIS) && get_trust(ch) < victim->pcdata->wizinvis)
return FALSE;
/* SB */
if (IS_NPC(victim) && xIS_SET(victim->act, ACT_MOBINVIS) && get_trust(ch) <= LEVEL_GUEST)
return FALSE;
if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
/* The miracle cure for blindness? -- Altrag */
if (!IS_AFFECTED(ch, AFF_TRUESIGHT))
{
if (IS_AFFECTED(ch, AFF_BLIND))
return FALSE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_AFFECTED(victim, AFF_INVISIBLE) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
if (IS_AFFECTED(victim, AFF_HIDE)
&& !IS_AFFECTED(ch, AFF_DETECT_HIDDEN))
return FALSE;
}
/* Redone by Narn to let newbie council members see pre-auths. */
/*
if (NOT_AUTHED(victim))
{
if (NOT_AUTHED(ch) || IS_IMMORTAL(ch) || IS_NPC(ch))
return TRUE;
if (ch->pcdata->council && !str_cmp(ch->pcdata->council->name, "Newbie Council"))
return TRUE;
return FALSE;
} */
return TRUE;
}
/*
* True if char can see obj.
*/
bool can_see_obj(CHAR_DATA * ch, OBJ_DATA * obj)
{
if (ch->coord->x > 0 || ch->coord->y > 0 || ch->map > -1
|| obj->coord->x > 0 || obj->coord->y > 0 || obj->map > -1)
{
if (ch->map != obj->map
|| ch->coord->x != obj->coord->x
|| ch->coord->y != obj->coord->y)
return FALSE;
}
if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
if (IS_NPC(ch) && ch->pIndexData->vnum == 3)
return TRUE;
if (IS_OBJ_STAT(obj, ITEM_BURIED))
return FALSE;
if (IS_AFFECTED(ch, AFF_TRUESIGHT))
return TRUE;
if (IS_AFFECTED(ch, AFF_BLIND))
return FALSE;
if (IS_OBJ_STAT(obj, ITEM_HIDDEN))
return FALSE;
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
return TRUE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_OBJ_STAT(obj, ITEM_INVIS) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
return TRUE;
}
/* Check for global obj checks on the map */
bool can_see_obj_map(CHAR_DATA * ch, OBJ_DATA * obj)
{
/* if ( IS_OBJ_STAT( obj, ITEM_ONMAP ) )
{
if( ch->map != obj->map
|| ch->coord->x != obj->coord->x
|| ch->coord->y != obj->coord->y )
return FALSE;
} */
if (!IS_NPC(ch) && xIS_SET(ch->act, PLR_HOLYLIGHT))
return TRUE;
if (IS_NPC(ch) && ch->pIndexData->vnum == 3)
return TRUE;
if (IS_OBJ_STAT(obj, ITEM_BURIED))
return FALSE;
if (IS_AFFECTED(ch, AFF_TRUESIGHT))
return TRUE;
if (IS_AFFECTED(ch, AFF_BLIND))
return FALSE;
if (IS_OBJ_STAT(obj, ITEM_HIDDEN))
return FALSE;
if (obj->item_type == ITEM_LIGHT && obj->value[2] != 0)
return TRUE;
if (room_is_dark(ch->in_room) && !IS_AFFECTED(ch, AFF_INFRARED))
return FALSE;
if (IS_OBJ_STAT(obj, ITEM_INVIS) && !IS_AFFECTED(ch, AFF_DETECT_INVIS))
return FALSE;
return TRUE;
}
/*
* True if char can drop obj.
*/
bool can_drop_obj(CHAR_DATA * ch, OBJ_DATA * obj)
{
if (!IS_OBJ_STAT(obj, ITEM_NODROP))
return TRUE;
if (!IS_NPC(ch) && ch->level >= LEVEL_IMMORTAL)
return TRUE;
if (IS_NPC(ch) && ch->pIndexData->vnum == 3)
return TRUE;
return FALSE;
}
// Need Color too -- 12/00
char *get_caste_color(int caste)
{
if (caste >= 1 && caste <= 10)
return "&Y";
if (caste >= 11 && caste <= 20)
return "&P";
if (caste >= 21 && caste <= 28)
return "&C";
if (caste >= 29 && caste <= 30)
return "&O";
if (caste >= 31 && caste <= 35)
return "&G&W";
return "&z";
}
/*
* Was getting tired of doing this manually -- Xerves 12/99
*/
char *get_caste_name(int caste, int sex)
{
if (caste > MAX_CASTE)
{
bug("get_caste_name: A caste that exceeded the max was found.", 0);
return "Casteless";
}
if (caste == 1)
return "Serf";
else if (caste == 2)
return "Peasant";
else if (caste == 3)
return "Laborer";
else if (caste == 4)
return "Apprentice";
else if (caste == 5)
return "Journeyman";
else if (caste == 6)
return "Master";
else if (caste == 7)
return "Merchant";
else if (caste == 8)
return "Trader";
else if (caste == 9 && sex == 0)
return "Businessman";
else if (caste == 9 && sex == 1)
return "Businessman";
else if (caste == 9 && sex == 2)
return "Businesswoman";
else if (caste == 10)
return "Mayor";
else if (caste == 11)
return "Page";
else if (caste == 12)
return "Squire";
else if (caste == 13)
return "Knight";
else if (caste == 14)
return "Baronet";
else if (caste == 15)
return "Baron";
else if (caste == 16)
return "Earl";
else if (caste == 17)
return "Viscount";
else if (caste == 18)
return "Count";
else if (caste == 19)
return "Duke";
else if (caste == 20)
return "Marquis";
else if (caste == 21)
return "Vassal";
else if (caste == 22)
return "Lord-Vassal";
else if (caste == 23)
return "Lord";
else if (caste == 24)
return "Hi-Lord";
else if (caste == 25)
return "Captain";
else if (caste == 26)
return "Minister";
else if (caste == 27 && sex == 0)
return "Prince";
else if (caste == 27 && sex == 1)
return "Prince";
else if (caste == 27 && sex == 2)
return "Princess";
else if (caste == 28 && sex == 0)
return "King";
else if (caste == 28 && sex == 1)
return "King";
else if (caste == 28 && sex == 2)
return "Queen";
else if (caste == 29)
return "Avatar";
else if (caste == 30)
return "Legend";
else if (caste == 31)
return "Ascender";
else if (caste == 32)
return "Immortal";
else if (caste == 33)
return "Being";
else if (caste == 34)
return "Staff";
else if (caste == 35)
return "Admin";
else
return "Casteless";
}
/*
* Return ascii name of an item type.
*/
char *item_type_name(OBJ_DATA * obj)
{
if (obj->item_type < 1 || obj->item_type > MAX_ITEM_TYPE)
{
bug("Item_type_name: unknown type %d.", obj->item_type);
return "(unknown)";
}
return o_types[obj->item_type];
}
/*
* Return ascii name of an affect location.
*/
char *affect_loc_name(int location)
{
switch (location)
{
case APPLY_NONE:
return "none";
case APPLY_ARMOR:
return "armor class";
case APPLY_SHIELD:
return "shield";
case APPLY_STONE:
return "stone skin";
case APPLY_SANCTIFY:
return "damage";
case APPLY_WMOD:
return "weightmod";
case APPLY_MANAFUSE:
return "manafuse";
case APPLY_FASTING:
return "fasting";
case APPLY_MANASHELL:
return "manashell";
case APPLY_MANASHIELD:
return "manashield";
case APPLY_MANAGUARD:
return "managuard";
case APPLY_MANABURN:
return "manaburn";
case APPLY_WEAPONCLAMP:
return "weaponclamp";
case APPLY_ARROWCATCH:
return "arrowcatch";
case APPLY_RFIRE:
return "rfire";
case APPLY_RWATER:
return "rwater";
case APPLY_RAIR:
return "rair";
case APPLY_REARTH:
return "rearth";
case APPLY_RENERGY:
return "renergy";
case APPLY_RMAGIC:
return "rmagic";
case APPLY_RNONMAGIC:
return "rnonmagic";
case APPLY_RBLUNT:
return "rblunt";
case APPLY_RPIERCE:
return "rpierce";
case APPLY_RSLASH:
return "rslash";
case APPLY_RPOISON:
return "rpoison";
case APPLY_RPARALYSIS:
return "rparalysis";
case APPLY_RHOLY:
return "rholy";
case APPLY_RUNHOLY:
return "runholy";
case APPLY_RUNDEAD:
return "rundead";
case APPLY_BRACING:
return "bracing";
case APPLY_HARDENING:
return "hardening";
case APPLY_TOHIT:
return "tohit";
case APPLY_MANATICK:
return "managen";
case APPLY_HPTICK:
return "hpgen";
case APPLY_STR:
return "strength";
case APPLY_DEX:
return "dexterity";
case APPLY_INT:
return "intelligence";
case APPLY_WIS:
return "wisdom";
case APPLY_CON:
return "constitution";
case APPLY_CHA:
return "charisma";
case APPLY_LCK:
return "luck";
case APPLY_SEX:
return "sex";
case APPLY_CLASS:
return "class";
case APPLY_LEVEL:
return "level";
case APPLY_AGE:
return "age";
case APPLY_MANA:
return "mana";
case APPLY_HIT:
return "hp";
case APPLY_MOVE:
return "moves";
case APPLY_GOLD:
return "gold";
case APPLY_EXP:
return "experience";
case APPLY_AC:
return "----------";
case APPLY_HITROLL:
return "hit roll";
case APPLY_DAMROLL:
return "damage roll";
case APPLY_SAVING_POISON:
return "save vs poison";
case APPLY_SAVING_ROD:
return "save vs rod";
case APPLY_SAVING_PARA:
return "save vs paralysis";
case APPLY_SAVING_BREATH:
return "save vs breath";
case APPLY_SAVING_SPELL:
return "save vs spell";
case APPLY_HEIGHT:
return "height";
case APPLY_WEIGHT:
return "weight";
case APPLY_AFFECT:
return "affected_by";
case APPLY_EXT_AFFECT:
return "xaffected_by";
case APPLY_RESISTANT:
return "resistant";
case APPLY_IMMUNE:
return "immune";
case APPLY_SUSCEPTIBLE:
return "susceptible";
case APPLY_BACKSTAB:
return "backstab";
case APPLY_PICK:
return "pick";
case APPLY_TRACK:
return "track";
case APPLY_STEAL:
return "steal";
case APPLY_SNEAK:
return "sneak";
case APPLY_HIDE:
return "hide";
case APPLY_PALM:
return "palm";
case APPLY_DETRAP:
return "detrap";
case APPLY_DODGE:
return "dodge";
case APPLY_PEEK:
return "peek";
case APPLY_SCAN:
return "scan";
case APPLY_GOUGE:
return "gouge";
case APPLY_SEARCH:
return "search";
case APPLY_MOUNT:
return "mount";
case APPLY_DISARM:
return "disarm";
case APPLY_KICK:
return "kick";
case APPLY_PARRY:
return "parry";
case APPLY_BASH:
return "bash";
case APPLY_STUN:
return "stun";
case APPLY_PUNCH:
return "punch";
case APPLY_CLIMB:
return "climb";
case APPLY_GRIP:
return "grip";
case APPLY_SCRIBE:
return "scribe";
case APPLY_BREW:
return "brew";
case APPLY_COOK:
return "cook";
case APPLY_WEAPONSPELL:
return "weapon spell";
case APPLY_WEARSPELL:
return "wear spell";
case APPLY_REMOVESPELL:
return "remove spell";
case APPLY_MENTALSTATE:
return "mental state";
case APPLY_EMOTION:
return "emotional state";
case APPLY_STRIPSN:
return "dispel";
case APPLY_REMOVE:
return "remove";
case APPLY_DIG:
return "dig";
case APPLY_FULL:
return "hunger";
case APPLY_THIRST:
return "thirst";
case APPLY_DRUNK:
return "drunk";
case APPLY_BLOOD:
return "blood";
case APPLY_RECURRINGSPELL:
return "recurring spell";
case APPLY_CONTAGIOUS:
return "contagious";
case APPLY_ODOR:
return "odor";
case APPLY_ROOMFLAG:
return "roomflag";
case APPLY_SECTORTYPE:
return "sectortype";
case APPLY_ROOMLIGHT:
return "roomlight";
case APPLY_TELEVNUM:
return "teleport vnum";
case APPLY_TELEDELAY:
return "teleport delay";
case APPLY_AGI:
return "agility";
};
bug("Affect_location_name: unknown location %d.", location);
return "(unknown)";
}
/*
* Return ascii name of an affect bit vector.
*/
char *affect_bit_name(EXT_BV * vector)
{
static char buf[512];
buf[0] = '\0';
if (xIS_SET(*vector, AFF_BLIND))
strcat(buf, " blind");
if (xIS_SET(*vector, AFF_INVISIBLE))
strcat(buf, " invisible");
if (xIS_SET(*vector, AFF_DETECT_EVIL))
strcat(buf, " detect_evil");
if (xIS_SET(*vector, AFF_DETECT_INVIS))
strcat(buf, " detect_invis");
if (xIS_SET(*vector, AFF_DETECT_MAGIC))
strcat(buf, " detect_magic");
if (xIS_SET(*vector, AFF_DETECT_HIDDEN))
strcat(buf, " detect_hidden");
if (xIS_SET(*vector, AFF_HOLD))
strcat(buf, " hold");
if (xIS_SET(*vector, AFF_SANCTUARY))
strcat(buf, " sanctuary");
if (xIS_SET(*vector, AFF_FAERIE_FIRE))
strcat(buf, " faerie_fire");
if (xIS_SET(*vector, AFF_INFRARED))
strcat(buf, " infrared");
if (xIS_SET(*vector, AFF_CURSE))
strcat(buf, " curse");
if (xIS_SET(*vector, AFF_FLAMING))
strcat(buf, " flaming");
if (xIS_SET(*vector, AFF_POISON))
strcat(buf, " poison");
if (xIS_SET(*vector, AFF_PROTECT))
strcat(buf, " protect");
if (xIS_SET(*vector, AFF_PARALYSIS))
strcat(buf, " paralysis");
if (xIS_SET(*vector, AFF_SLEEP))
strcat(buf, " sleep");
if (xIS_SET(*vector, AFF_SNEAK))
strcat(buf, " sneak");
if (xIS_SET(*vector, AFF_HIDE))
strcat(buf, " hide");
if (xIS_SET(*vector, AFF_CHARM))
strcat(buf, " charm");
if (xIS_SET(*vector, AFF_POSSESS))
strcat(buf, " possess");
if (xIS_SET(*vector, AFF_FLYING))
strcat(buf, " flying");
if (xIS_SET(*vector, AFF_PASS_DOOR))
strcat(buf, " pass_door");
if (xIS_SET(*vector, AFF_FLOATING))
strcat(buf, " floating");
if (xIS_SET(*vector, AFF_TRUESIGHT))
strcat(buf, " true_sight");
if (xIS_SET(*vector, AFF_DETECTTRAPS))
strcat(buf, " detect_traps");
if (xIS_SET(*vector, AFF_SCRYING))
strcat(buf, " scrying");
if (xIS_SET(*vector, AFF_FIRESHIELD))
strcat(buf, " fireshield");
if (xIS_SET(*vector, AFF_SHOCKSHIELD))
strcat(buf, " shockshield");
if (xIS_SET(*vector, AFF_ICESHIELD))
strcat(buf, " iceshield");
if (xIS_SET(*vector, AFF_BERSERK))
strcat(buf, " berserk");
if (xIS_SET(*vector, AFF_AQUA_BREATH))
strcat(buf, " aqua_breath");
if (xIS_SET(*vector, AFF_RECURRINGSPELL))
strcat(buf, " recurringspell");
if (xIS_SET(*vector, AFF_CONTAGIOUS))
strcat(buf, " contagious");
if (xIS_SET(*vector, AFF_WIZARDEYE))
strcat(buf, " wizardeye");
if (xIS_SET(*vector, AFF_E_WIZARDEYE))
strcat(buf, " wizardeye");
if (xIS_SET(*vector, AFF_M_WIZARDEYE))
strcat(buf, " wizardeye");
if (xIS_SET(*vector, AFF_BALANCE))
strcat(buf, " balance");
if (xIS_SET(*vector, AFF_NOHUNGER))
strcat(buf, " nohunger");
if (xIS_SET(*vector, AFF_NOTHIRST))
strcat(buf, " nothirst");
if (xIS_SET(*vector, AFF_GAGGED))
strcat(buf, " gagged");
if (xIS_SET(*vector, AFF_REZ))
strcat(buf, " rez");
if (xIS_SET(*vector, AFF_WEB))
strcat(buf, " web");
if (xIS_SET(*vector, AFF_SNARE))
strcat(buf, " snare");
if (xIS_SET(*vector, AFF_NERVEPINCH))
strcat(buf, " nervepinch");
if (xIS_SET(*vector, AFF_NYIJI))
strcat(buf, " nyiji");
if (xIS_SET(*vector, AFF_STALK))
strcat(buf, " stalk");
return (buf[0] != '\0') ? buf + 1 : "none";
}
/*
* Return ascii name of extra flags vector.
*/
char *extra_bit_name(EXT_BV * extra_flags)
{
static char buf[512];
buf[0] = '\0';
if (xIS_SET(*extra_flags, ITEM_GLOW))
strcat(buf, " glow");
if (xIS_SET(*extra_flags, ITEM_HUM))
strcat(buf, " hum");
if (xIS_SET(*extra_flags, ITEM_DARK))
strcat(buf, " dark");
if (xIS_SET(*extra_flags, ITEM_LOYAL))
strcat(buf, " loyal");
if (xIS_SET(*extra_flags, ITEM_EVIL))
strcat(buf, " evil");
if (xIS_SET(*extra_flags, ITEM_INVIS))
strcat(buf, " invis");
if (xIS_SET(*extra_flags, ITEM_MAGIC))
strcat(buf, " magic");
if (xIS_SET(*extra_flags, ITEM_NODROP))
strcat(buf, " nodrop");
if (xIS_SET(*extra_flags, ITEM_BLESS))
strcat(buf, " bless");
if (xIS_SET(*extra_flags, ITEM_ANTI_GOOD))
strcat(buf, " anti-good");
if (xIS_SET(*extra_flags, ITEM_ANTI_EVIL))
strcat(buf, " anti-evil");
if (xIS_SET(*extra_flags, ITEM_ANTI_NEUTRAL))
strcat(buf, " anti-neutral");
if (xIS_SET(*extra_flags, ITEM_NOREMOVE))
strcat(buf, " noremove");
if (xIS_SET(*extra_flags, ITEM_INVENTORY))
strcat(buf, " inventory");
if (xIS_SET(*extra_flags, ITEM_DEATHROT))
strcat(buf, " deathrot");
if (xIS_SET(*extra_flags, ITEM_GROUNDROT))
strcat(buf, " groundrot");
if (xIS_SET(*extra_flags, ITEM_ANTI_MAGE))
strcat(buf, " anti-mage");
if (xIS_SET(*extra_flags, ITEM_ANTI_THIEF))
strcat(buf, " anti-thief");
if (xIS_SET(*extra_flags, ITEM_ANTI_WARRIOR))
strcat(buf, " anti-warrior");
if (xIS_SET(*extra_flags, ITEM_ANTI_CLERIC))
strcat(buf, " anti-cleric");
if (xIS_SET(*extra_flags, ITEM_ANTI_DRUID))
strcat(buf, " anti-druid");
if (xIS_SET(*extra_flags, ITEM_ANTI_VAMPIRE))
strcat(buf, " anti-vampire");
if (xIS_SET(*extra_flags, ITEM_ANTI_PALADIN))
strcat(buf, " anti-paladin");
if (xIS_SET(*extra_flags, ITEM_ANTI_MONK))
strcat(buf, " anti-monk");
if (xIS_SET(*extra_flags, ITEM_ANTI_AUGURER))
strcat(buf, " anti-augurer");
if (xIS_SET(*extra_flags, ITEM_ANTI_RANGER))
strcat(buf, " anti-ranger");
if (xIS_SET(*extra_flags, ITEM_ORGANIC))
strcat(buf, " organic");
if (xIS_SET(*extra_flags, ITEM_METAL))
strcat(buf, " metal");
if (xIS_SET(*extra_flags, ITEM_DONATION))
strcat(buf, " donation");
if (xIS_SET(*extra_flags, ITEM_CLANOBJECT))
strcat(buf, " clan");
if (xIS_SET(*extra_flags, ITEM_CLANCORPSE))
strcat(buf, " clanbody");
if (xIS_SET(*extra_flags, ITEM_PROTOTYPE))
strcat(buf, " prototype");
if (xIS_SET(*extra_flags, ITEM_NOGIVE))
strcat(buf, " nogive");
if (xIS_SET(*extra_flags, ITEM_NOPURGE))
strcat(buf, " nopurge");
return (buf[0] != '\0') ? buf + 1 : "none";
}
/*
* Return ascii name of magic flags vector. - Scryn
*/
char *magic_bit_name(int magic_flags)
{
static char buf[512];
buf[0] = '\0';
if (magic_flags & ITEM_RETURNING)
strcat(buf, " returning");
return (buf[0] != '\0') ? buf + 1 : "none";
}
/*
* Return ascii name of pulltype exit setting.
*/
char *pull_type_name(int pulltype)
{
if (pulltype >= PT_FIRE)
return ex_pfire[pulltype - PT_FIRE];
if (pulltype >= PT_AIR)
return ex_pair[pulltype - PT_AIR];
if (pulltype >= PT_EARTH)
return ex_pearth[pulltype - PT_EARTH];
if (pulltype >= PT_WATER)
return ex_pwater[pulltype - PT_WATER];
if (pulltype < 0)
return "ERROR";
return ex_pmisc[pulltype];
}
/*
* Set off a trap (obj) upon character (ch) -Thoric
*/
ch_ret spring_trap(CHAR_DATA * ch, OBJ_DATA * obj, TRAP_DATA *trap)
{
int dam;
int typ;
int lev;
char *txt;
char buf[MSL];
ch_ret retcode;
CHAR_DATA *victim;
CHAR_DATA *victim_next;
if (trap)
{
typ = trap->type;
lev = (trap->damlow + trap->damhigh) / 2;
lev = URANGE(3, lev, 90);
}
else
{
typ = obj->value[1];
lev = obj->value[2];
}
retcode = rNONE;
switch (typ)
{
default:
txt = "hit by a trap";
break;
case TRAP_TYPE_POISON_GAS:
txt = "surrounded by a green cloud of gas";
break;
case TRAP_TYPE_POISON_DART:
txt = "hit by a dart";
break;
case TRAP_TYPE_POISON_NEEDLE:
txt = "pricked by a needle";
break;
case TRAP_TYPE_POISON_DAGGER:
txt = "stabbed by a dagger";
break;
case TRAP_TYPE_POISON_ARROW:
txt = "struck with an arrow";
break;
case TRAP_TYPE_BLINDNESS_GAS:
txt = "surrounded by a red cloud of gas";
break;
case TRAP_TYPE_SLEEPING_GAS:
txt = "surrounded by a yellow cloud of gas";
break;
case TRAP_TYPE_FLAME:
txt = "struck by a burst of flame";
break;
case TRAP_TYPE_EXPLOSION:
txt = "hit by an explosion";
break;
case TRAP_TYPE_ACID_SPRAY:
txt = "covered by a spray of acid";
break;
case TRAP_TYPE_ELECTRIC_SHOCK:
txt = "suddenly shocked";
break;
case TRAP_TYPE_BLADE:
txt = "sliced by a razor sharp blade";
break;
case TRAP_TYPE_SEX_CHANGE:
txt = "surrounded by a mysterious aura";
break;
}
if (trap)
dam = number_range(trap->damlow, trap->damhigh);
else
dam = number_range(obj->value[2], obj->value[2] * 2);
sprintf(buf, "You are %s!", txt);
act(AT_RED, buf, ch, NULL, NULL, TO_CHAR);
sprintf(buf, "$n is %s!", txt);
act(AT_RED, buf, ch, NULL, NULL, TO_ROOM);
if (trap)
{
RESET_DATA *pReset;
int rfound = 0;
--trap->charges;
if (trap->onetime == 1 && trap->area)
{
for (pReset = trap->area->first_reset; pReset; pReset = pReset->next)
{
if (pReset->command == 'A' && pReset->arg1 == trap->uid)
{
delete_reset(trap->area, pReset);
fold_area(trap->area, trap->area->filename, FALSE, 1);
trap->obj->trap = NULL;
trap->obj = NULL;
trap->area = NULL;
rfound = 1;
break;
}
}
if (!rfound)
bug("Trap of uid %d was flagged onetime but could not be found to delete reset.", trap->uid);
}
}
else
{
--obj->value[0];
if (obj->value[0] <= 0)
extract_obj(obj);
}
//spring it on others in the room, disable room fire then re-enable it
if (trap && trap->room == 1)
{
int charges;
charges = trap->charges;
trap->room = 0;
for (victim = ch->in_room->first_person; victim; victim = victim_next)
{
victim_next = victim->next_in_room;
if (IN_SAME_ROOM(ch, victim) && victim != ch)
spring_trap(victim, NULL, trap);
}
trap->charges = charges;
trap->room = 1;
}
switch (typ)
{
default:
case TRAP_TYPE_POISON_DART:
case TRAP_TYPE_POISON_NEEDLE:
case TRAP_TYPE_POISON_DAGGER:
case TRAP_TYPE_POISON_ARROW:
/* hmm... why not use spell_poison() here? */
retcode = obj_cast_spell(gsn_poison, lev, ch, ch, NULL);
if (retcode == rNONE)
retcode = damage(ch, ch, dam, TYPE_UNDEFINED, 0, number_range(LM_BODY, LM_NECK));
break;
case TRAP_TYPE_POISON_GAS:
retcode = obj_cast_spell(gsn_poison, lev, ch, ch, NULL);
break;
case TRAP_TYPE_BLINDNESS_GAS:
retcode = obj_cast_spell(gsn_blindness, lev, ch, ch, NULL);
break;
case TRAP_TYPE_SLEEPING_GAS:
retcode = obj_cast_spell(skill_lookup("sleep"), lev, ch, ch, NULL);
break;
case TRAP_TYPE_SEX_CHANGE:
break;
case TRAP_TYPE_ACID_SPRAY:
case TRAP_TYPE_FLAME:
case TRAP_TYPE_EXPLOSION:;
case TRAP_TYPE_ELECTRIC_SHOCK:
case TRAP_TYPE_BLADE:
retcode = damage(ch, ch, dam, TYPE_UNDEFINED, 0, number_range(LM_BODY, LM_NECK));
}
return retcode;
}
ch_ret pre_spring_trap(CHAR_DATA * ch, OBJ_DATA * obj, TRAP_DATA *trap, OBJ_DATA *trapobj)
{
int frag = 0;
if (trap)
{
if (trap->frag)
{
if (number_range(1, 100) <= trap->frag)
{
act(AT_DGREY, "The trap armed on $p fires. The force of the trap shatters $p into pieces", ch, trapobj, NULL, TO_ROOM);
act(AT_DGREY, "The trap armed on $p fires. The force of the trap shatters $p into pieces", ch, trapobj, NULL, TO_CHAR);
frag = 1;
}
}
global_retcode = spring_trap(ch, obj, trap);
if (trap->charges <= 0 && trap->uid >= START_INV_TRAP)
{
UNLINK(trap, first_trap, last_trap, next, prev);
trapobj->trap = NULL;
DISPOSE(trapobj->trap);
save_trap_file(NULL, NULL);
}
if (frag == 1)
{
extract_obj(trapobj);
global_retcode = rOBJ_SCRAPPED;
}
}
else
{
global_retcode = spring_trap(ch, obj, obj->trap);
}
return global_retcode;
}
/*
* Check an object for a trap -Thoric
*/
ch_ret check_for_trap(CHAR_DATA * ch, OBJ_DATA * obj, int flag, int newflag)
{
OBJ_DATA *check;
ch_ret retcode;
global_retcode = rNONE;
if (obj->trap)
{
if (newflag == -1)
return rNONE;
if (obj->trap->charges < 1)
return rNONE;
if (xIS_SET(obj->trap->trapflags, newflag))
{
if (newflag == NEW_TRAP_GET)
{
act(AT_RED, "As $n attempts to get something from $p, a trap is fired.", ch, obj, NULL, TO_ROOM);
act(AT_RED, "As you attempt to get something from $p, a trap is fired.", ch, obj, NULL, TO_CHAR);
}
return pre_spring_trap(ch, NULL, obj->trap, obj);
}
else
return rNONE;
}
if (flag == -1)
return rNONE;
if (!obj->first_content)
return rNONE;
retcode = rNONE;
for (check = obj->first_content; check; check = check->next_content)
if (check->item_type == ITEM_TRAP && IS_SET(check->value[3], flag))
{
retcode = spring_trap(ch, check, NULL);
if (retcode != rNONE)
return retcode;
}
return retcode;
}
/*
* Check the room for a trap -Thoric
*/
ch_ret check_room_for_traps(CHAR_DATA * ch, int flag)
{
OBJ_DATA *check;
ch_ret retcode;
retcode = rNONE;
if (!ch)
return rERROR;
if (!ch->in_room || !ch->in_room->first_content)
return rNONE;
for (check = ch->in_room->first_content; check; check = check->next_content)
{
if (check->item_type == ITEM_TRAP && IS_SET(check->value[3], flag))
{
retcode = spring_trap(ch, check, NULL);
if (retcode != rNONE)
return retcode;
}
}
return retcode;
}
/*
* return TRUE if an object contains a trap -Thoric
*/
bool is_trapped(OBJ_DATA * obj)
{
OBJ_DATA *check;
if (obj->trap)
{
if (obj->trap->charges > 0)
return TRUE;
}
if (!obj->first_content)
return FALSE;
for (check = obj->first_content; check; check = check->next_content)
if (check->item_type == ITEM_TRAP)
return TRUE;
return FALSE;
}
/*
* If an object contains a trap, return the pointer to the trap -Thoric
*/
OBJ_DATA *get_trap(OBJ_DATA * obj)
{
OBJ_DATA *check;
if (!obj->first_content)
return NULL;
for (check = obj->first_content; check; check = check->next_content)
if (check->item_type == ITEM_TRAP)
return check;
return NULL;
}
/*
* Return a pointer to the first object of a certain type found that
* a player is carrying/wearing
*/
OBJ_DATA *get_objtype(CHAR_DATA * ch, sh_int type)
{
OBJ_DATA *obj;
for (obj = ch->first_carrying; obj; obj = obj->next_content)
if (obj->item_type == type)
return obj;
return NULL;
}
/*
* Remove an exit from a room -Thoric
*/
void extract_exit(ROOM_INDEX_DATA * room, EXIT_DATA * pexit)
{
UNLINK(pexit, room->first_exit, room->last_exit, next, prev);
if (pexit->rexit)
pexit->rexit->rexit = NULL;
STRFREE(pexit->keyword);
STRFREE(pexit->description);
if (pexit->coord)
DISPOSE(pexit->coord);
DISPOSE(pexit);
}
/*
* Remove a room
*/
void extract_room(ROOM_INDEX_DATA * room)
{
bug("extract_room: not implemented", 0);
/*
(remove room from hash table)
clean_room( room )
DISPOSE( room );
*/
return;
}
/*
* clean out a room (leave list pointers intact ) -Thoric
*/
void clean_room(ROOM_INDEX_DATA * room)
{
EXTRA_DESCR_DATA *ed, *ed_next;
EXIT_DATA *pexit, *pexit_next;
STRFREE(room->description);
STRFREE(room->name);
for (ed = room->first_extradesc; ed; ed = ed_next)
{
ed_next = ed->next;
STRFREE(ed->description);
STRFREE(ed->keyword);
DISPOSE(ed);
top_ed--;
}
room->first_extradesc = NULL;
room->last_extradesc = NULL;
for (pexit = room->first_exit; pexit; pexit = pexit_next)
{
pexit_next = pexit->next;
STRFREE(pexit->keyword);
STRFREE(pexit->description);
DISPOSE(pexit);
top_exit--;
}
room->first_exit = NULL;
room->last_exit = NULL;
xCLEAR_BITS(room->room_flags);
room->sector_type = 0;
room->light = 0;
}
/*
* clean out an object (index) (leave list pointers intact ) -Thoric
*/
void clean_obj(OBJ_INDEX_DATA * obj)
{
AFFECT_DATA *paf;
AFFECT_DATA *paf_next;
EXTRA_DESCR_DATA *ed;
EXTRA_DESCR_DATA *ed_next;
STRFREE(obj->name);
STRFREE(obj->short_descr);
STRFREE(obj->description);
STRFREE(obj->action_desc);
obj->item_type = 0;
xCLEAR_BITS(obj->extra_flags);
obj->wear_flags = 0;
obj->count = 0;
obj->weight = 0;
obj->cost = 0;
obj->value[0] = 0;
obj->value[1] = 0;
obj->value[2] = 0;
obj->value[3] = 0;
for (paf = obj->first_affect; paf; paf = paf_next)
{
paf_next = paf->next;
DISPOSE(paf);
top_affect--;
}
obj->first_affect = NULL;
obj->last_affect = NULL;
for (ed = obj->first_extradesc; ed; ed = ed_next)
{
ed_next = ed->next;
STRFREE(ed->description);
STRFREE(ed->keyword);
DISPOSE(ed);
top_ed--;
}
obj->first_extradesc = NULL;
obj->last_extradesc = NULL;
}
/*
* clean out a mobile (index) (leave list pointers intact ) -Thoric
*/
void clean_mob(MOB_INDEX_DATA * mob)
{
MPROG_DATA *mprog, *mprog_next;
STRFREE(mob->player_name);
STRFREE(mob->short_descr);
STRFREE(mob->long_descr);
STRFREE(mob->description);
mob->spec_fun = NULL;
mob->pShop = NULL;
mob->rShop = NULL;
xCLEAR_BITS(mob->progtypes);
for (mprog = mob->mudprogs; mprog; mprog = mprog_next)
{
mprog_next = mprog->next;
STRFREE(mprog->arglist);
STRFREE(mprog->comlist);
DISPOSE(mprog);
}
mob->count = 0;
mob->killed = 0;
mob->sex = 0;
mob->level = 0;
xCLEAR_BITS(mob->act);
xCLEAR_BITS(mob->affected_by);
mob->alignment = 0;
mob->mobthac0 = 0;
mob->ac = 0;
mob->hitnodice = 0;
mob->hitsizedice = 0;
mob->hitplus = 0;
mob->damnodice = 0;
mob->damsizedice = 0;
mob->damplus = 0;
mob->gold = 0;
mob->position = 0;
mob->defposition = 0;
mob->height = 0;
mob->weight = 0; /* mob->vnum = 0; */
xCLEAR_BITS(mob->attacks);
xCLEAR_BITS(mob->defenses);
}
extern int top_reset;
/*
* Remove all resets from an area -Thoric
*/
void clean_resets(AREA_DATA * tarea)
{
RESET_DATA *pReset, *pReset_next;
for (pReset = tarea->first_reset; pReset; pReset = pReset_next)
{
pReset_next = pReset->next;
DISPOSE(pReset);
--top_reset;
}
tarea->first_reset = NULL;
tarea->last_reset = NULL;
}
/*
* "Roll" players stats based on the character name -Thoric
*/
/*
void name_stamp_stats( CHAR_DATA *ch )
{
int x, a, b, c;
for ( x = 0; x < strlen(ch->name); x++ )
{
c = ch->name[x] + x;
b = c % 14;
a = (c % 1) + 1;
switch (b)
{
case 0:
ch->perm_str = UMIN( 18, ch->perm_str + a );
break;
case 1:
ch->perm_dex = UMIN( 18, ch->perm_dex + a );
break;
case 2:
ch->perm_wis = UMIN( 18, ch->perm_wis + a );
break;
case 3:
ch->perm_int = UMIN( 18, ch->perm_int + a );
break;
case 4:
ch->perm_con = UMIN( 18, ch->perm_con + a );
break;
case 5:
ch->perm_cha = UMIN( 18, ch->perm_cha + a );
break;
case 6:
ch->perm_lck = UMIN( 18, ch->perm_lck + a );
break;
case 7:
ch->perm_agi = UMIN( 18, ch->perm_agi + a);
break;
case 8:
ch->perm_str = UMAX( 9, ch->perm_str - a );
break;
case 9:
ch->perm_dex = UMAX( 9, ch->perm_dex - a );
break;
case 10:
ch->perm_wis = UMAX( 9, ch->perm_wis - a );
break;
case 11:
ch->perm_int = UMAX( 9, ch->perm_int - a );
break;
case 12:
ch->perm_con = UMAX( 9, ch->perm_con - a );
break;
case 13:
ch->perm_cha = UMAX( 9, ch->perm_cha - a );
break;
case 14:
ch->perm_lck = UMAX( 9, ch->perm_lck - a );
break;
case 15:
ch->perm_agi = UMAX( 9, ch->perm_agi - a );
break;
}
}
}
--Removed for Stat rolling Xerves */
/*
* "Roll" players stats based on the character name -Thoric
*/
/* Rewritten by Whir. Thanks to Vor/Casteele for help 2-1-98 */
/* Racial bonus calculations moved to this function and removed
from comm.c - Samson 2-2-98 */
/* Updated to AD&D standards by Samson 9-5-98 */
/* Changed to use internal random number generator instead of
OS dependant random() function - Samson 9-5-98 */
/* OOH long list, Added support for Prime Stats, and adding
some HP/Mana/Prac/Train support also -- Xerves 8-1-99*/
// More Changes for 2.0 the comments GROW!!!! -- Xerves 6-01
void name_stamp_stats(CHAR_DATA * ch)
{
ch->perm_str = 14 + race_table[ch->race]->str_plus;
ch->perm_dex = 14 + race_table[ch->race]->dex_plus;
ch->perm_wis = 14 + race_table[ch->race]->wis_plus;
ch->perm_int = 14 + race_table[ch->race]->int_plus;
ch->perm_con = 14 + race_table[ch->race]->con_plus;
ch->perm_lck = 14 + race_table[ch->race]->lck_plus;
ch->perm_agi = race_table[ch->race]->agi_start;
ch->perm_cha = 14;
ch->pcdata->lore = dice(5, 2);
ch->max_hit = 18 + dice(3, 3);
ch->max_mana = 50 + dice(5, 5);
ch->max_move = 1000;
ch->gold = 12000 + dice(200, 10);
ch->max_hit += race_table[ch->race]->hit;
ch->max_mana += race_table[ch->race]->mana;
ch->move = ch->max_move;
ch->hit = ch->max_hit;
ch->mana = ch->max_mana;
}
/*
* "Fix" a character's stats -Thoric
*/
void fix_char(CHAR_DATA * ch)
{
AFFECT_DATA *aff;
CHAR_DATA *temp;
OBJ_DATA *carry[200]; //if they have more than this they need to have them removed
OBJ_DATA *obj;
int x, ncarry;
de_equip_char(ch);
ncarry = 0;
while ((obj = ch->first_carrying) != NULL)
{
if (ncarry >= 200)
{
bug("%s has too many objects in his/her inventory.", ch->name);
break;
}
carry[ncarry++] = obj;
obj_from_char(obj);
}
for (aff = ch->first_affect; aff; aff = aff->next)
affect_modify(ch, aff, FALSE);
xCLEAR_BITS(ch->affected_by);
xSET_BITS(ch->affected_by, race_table[ch->race]->affected);
ch->mental_state = -10;
ch->hit = UMAX(1, ch->hit);
ch->mana = UMAX(1, ch->mana);
ch->move = UMAX(1, ch->move);
ch->armor = 0;
ch->mod_str = 0;
ch->mod_dex = 0;
ch->mod_wis = 0;
ch->mod_int = 0;
ch->mod_con = 0;
ch->mod_cha = 0;
ch->mod_lck = 0;
ch->mod_agi = 0;
ch->damroll = 0;
ch->hitroll = 0;
ch->alignment = URANGE(-1000, ch->alignment, 1000);
ch->saving_breath = 0;
ch->saving_wand = 0;
ch->saving_para_petri = 0;
ch->saving_spell_staff = 0;
ch->saving_poison_death = 0;
for (aff = ch->first_affect; aff; aff = aff->next)
affect_modify(ch, aff, TRUE);
for (x = 0; x < ncarry; x++)
{
temp = loading_char;
loading_char = ch;
obj_to_char(carry[x], ch);
loading_char = temp;
}
re_equip_char(ch);
}
char *specgem_loc_name(int type)
{
//1000 - Damage 1001 - Durability 1002 - TohitBash 1003 - TohitStab 1004 - TohitSlash
//1005 - Weight 1006 - Shieldlag 1007 - Blocking % 1008 - Proj Range 1009 - Parry Chance 1010 - Stop Parry
//1011 - SpellSN 1012 - SpellStr 1013 - Unbeakable 1014 - Nodisarm 1015 - Sanctified 1016 - Change Size
if (type == 1000)
return "Spec Damage";
else if (type == 1001)
return "Spec Durability";
else if (type == 1002)
return "Spec ToHitBash";
else if (type == 1003)
return "Spec ToHitStab";
else if (type == 1004)
return "Spec ToHitSlash";
else if (type == 1005)
return "Spec Weight";
else if (type == 1006)
return "Spec Shieldlag";
else if (type == 1007)
return "Spec Blocking Percent";
else if (type == 1008)
return "Spec Projectile Range";
else if (type == 1009)
return "Spec Parry Chance";
else if (type == 1010)
return "Spec Stop Parry";
else if (type == 1011)
return "Spec Spell";
else if (type == 1012)
return "Spec Spell Strength";
else if (type == 1013)
return "Spec Unbreakable Flag";
else if (type == 1014)
return "Spec Nodisarm Flag";
else if (type == 1015)
return "Spec Sanctified Flag";
else if (type == 1016)
return "Spec Change Size";
else if (type == 1017)
return "Spec Saves";
else
return "Unknown Spec";
}
/*
* Show an affect verbosely to a character -Thoric
*/
char *showgemaff(CHAR_DATA * ch, OBJ_DATA *obj, int passbuf, IMBUE_DATA *imbue)
{
char buf[MSL];
static char pbuf[MSL];
char buf2[MSL];
int x;
int cnt;
int v1, v2, v3, v4;
strcpy(pbuf, "");
if (!obj && !imbue)
{
bug("showgemaff: NULL obj and imbue", 0);
return NULL;
}
for (cnt = 0; cnt < 12; cnt+=4)
{
strcpy(buf, "");
if (obj)
{
v1 = obj->value[cnt];
v2 = obj->value[cnt+1];
v3 = obj->value[cnt+2];
v4 = obj->value[cnt+3];
}
else
{
if (cnt == 0)
{
v1 = imbue->type;
v2 = imbue->sworth;
v3 = imbue->lowvalue;
v4 = imbue->highvalue;
}
else if (cnt == 4)
{
v1 = imbue->type2;
v2 = imbue->sworth2;
v3 = imbue->lowvalue2;
v4 = imbue->highvalue2;
}
else
{
v1 = imbue->type3;
v2 = imbue->sworth3;
v3 = imbue->lowvalue3;
v4 = imbue->highvalue3;
}
}
if (v1 != APPLY_NONE && v3 != 0)
{
switch (v1)
{
default:
if (v1 >= 1000)
{
if (v1 == 1011)
{
sprintf(buf, " Adds %s %s (%d Sworth).\n\r", specgem_loc_name(v1), skill_table[v3]->name,
v2);
}
else if (v1 == 1012)
{
sprintf(buf, " Adds %s %s from %s (%d Sworth).\n\r", specgem_loc_name(v1), get_wplevel(v3),
get_wplevel(v4), v2);
}
else
{
sprintf(buf, " Adds %s by %d to %d (%d Sworth).\n\r", specgem_loc_name(v1), v3,
v4, v2);
}
}
else
{
sprintf(buf, " Adds %s by %d to %d (%d Sworth).\n\r", affect_loc_name(v1), v3,
v4, v2);
}
break;
case APPLY_EXT_AFFECT:
sprintf(buf, " Adds %s by %s (%d Sworth).\n\r", affect_loc_name(v1), a_flags[v3], v2);
break;
case APPLY_AFFECT:
sprintf(buf, " Adds %s by", affect_loc_name(v1));
for (x = 0; x < 32; x++)
if (IS_SET(v3, 1 << x))
{
strcat(buf, " ");
strcat(buf, a_flags[x]);
}
sprintf(buf2, " (%d Sworth)", v2);
strcat(buf, buf2);
strcat(buf, "\n\r");
break;
case APPLY_WEAPONSPELL:
case APPLY_WEARSPELL:
case APPLY_REMOVESPELL:
sprintf(buf, " Adds spell '%s' (%d Sworth)\n\r", IS_VALID_SN(v3) ? skill_table[v3]->name : "unknown",
v2);
break;
case APPLY_RESISTANT:
case APPLY_IMMUNE:
case APPLY_SUSCEPTIBLE:
sprintf(buf, " Adds %s by", affect_loc_name(v1));
for (x = 0; x < 32; x++)
if (IS_SET(v3, 1 << x))
{
strcat(buf, " ");
strcat(buf, ris_flags[x]);
}
sprintf(buf2, " (%d Sworth)", v2);
strcat(buf, buf2);
strcat(buf, "\n\r");
break;
}
}
strcat(pbuf, buf);
}
if (!passbuf)
send_to_char(pbuf, ch);
else
return pbuf;
return NULL;
}
/*
* Show an affect verbosely to a character -Thoric
*/
char *showaffect(CHAR_DATA * ch, AFFECT_DATA * paf, int passbuf)
{
static char buf[MSL];
int x;
strcpy(buf, "");
if (!paf)
{
bug("showaffect: NULL paf", 0);
return NULL;
}
if (paf->location != APPLY_NONE && paf->modifier != 0)
{
switch (paf->location)
{
default:
sprintf(buf, "Affects %s by %d.\n\r", affect_loc_name(paf->location), paf->modifier);
break;
case APPLY_EXT_AFFECT:
sprintf(buf, "Affects %s by %s.\n\r", affect_loc_name(paf->location), a_flags[paf->modifier]);
break;
case APPLY_AFFECT:
sprintf(buf, "Affects %s by", affect_loc_name(paf->location));
for (x = 0; x < 32; x++)
if (IS_SET(paf->modifier, 1 << x))
{
strcat(buf, " ");
strcat(buf, a_flags[x]);
}
strcat(buf, "\n\r");
break;
case APPLY_WEAPONSPELL:
case APPLY_WEARSPELL:
case APPLY_REMOVESPELL:
sprintf(buf, "Casts spell '%s'\n\r", IS_VALID_SN(paf->modifier) ? skill_table[paf->modifier]->name : "unknown");
break;
case APPLY_RESISTANT:
case APPLY_IMMUNE:
case APPLY_SUSCEPTIBLE:
sprintf(buf, "Affects %s by", affect_loc_name(paf->location));
for (x = 0; x < 32; x++)
if (IS_SET(paf->modifier, 1 << x))
{
strcat(buf, " ");
strcat(buf, ris_flags[x]);
}
strcat(buf, "\n\r");
break;
}
if (!passbuf)
send_to_char(buf, ch);
else
return buf;
}
return NULL;
}
/*
* Set the current global object to obj -Thoric
*/
void set_cur_obj(OBJ_DATA * obj)
{
cur_obj = obj->serial;
cur_obj_extracted = FALSE;
global_objcode = rNONE;
}
/*
* Check the recently extracted object queue for obj -Thoric
*/
bool obj_extracted(OBJ_DATA * obj)
{
OBJ_DATA *cod;
if (obj->serial == cur_obj && cur_obj_extracted)
return TRUE;
for (cod = extracted_obj_queue; cod; cod = cod->next)
if (obj == cod)
return TRUE;
return FALSE;
}
/*
* Stick obj onto extraction queue
*/
void queue_extracted_obj(OBJ_DATA * obj)
{
++cur_qobjs;
obj->next = extracted_obj_queue;
extracted_obj_queue = obj;
}
/*
* Clean out the extracted object queue
*/
void clean_obj_queue()
{
OBJ_DATA *obj;
while (extracted_obj_queue)
{
obj = extracted_obj_queue;
extracted_obj_queue = extracted_obj_queue->next;
STRFREE(obj->name);
STRFREE(obj->description);
STRFREE(obj->short_descr);
STRFREE(obj->action_desc);
if (obj->coord)
DISPOSE(obj->coord);
DISPOSE(obj);
--cur_qobjs;
}
}
/*
* Set the current global character to ch -Thoric
*/
void set_cur_char(CHAR_DATA * ch)
{
cur_char = ch;
cur_char_died = FALSE;
cur_room = ch->in_room;
global_retcode = rNONE;
}
/*
* Check to see if ch died recently -Thoric
*/
bool char_died(CHAR_DATA * ch)
{
EXTRACT_CHAR_DATA *ccd;
if (ch == cur_char && cur_char_died)
return TRUE;
for (ccd = extracted_char_queue; ccd; ccd = ccd->next)
if (ccd->ch == ch)
return TRUE;
return FALSE;
}
/*
* Add ch to the queue of recently extracted characters -Thoric
*/
void queue_extracted_char(CHAR_DATA * ch, bool extract)
{
EXTRACT_CHAR_DATA *ccd;
if (!ch)
{
bug("queue_extracted char: ch = NULL", 0);
return;
}
CREATE(ccd, EXTRACT_CHAR_DATA, 1);
ccd->ch = ch;
ccd->room = ch->in_room;
ccd->extract = extract;
if (ch == cur_char)
ccd->retcode = global_retcode;
else
ccd->retcode = rCHAR_DIED;
ccd->next = extracted_char_queue;
extracted_char_queue = ccd;
cur_qchars++;
}
/*
* clean out the extracted character queue
*/
void clean_char_queue()
{
EXTRACT_CHAR_DATA *ccd;
for (ccd = extracted_char_queue; ccd; ccd = extracted_char_queue)
{
extracted_char_queue = ccd->next;
if (ccd->extract)
free_char(ccd->ch);
DISPOSE(ccd);
--cur_qchars;
}
}
/*
* Add a timer to ch -Thoric
* Support for "call back" time delayed commands
*/
void add_timer(CHAR_DATA * ch, sh_int type, sh_int count, DO_FUN * fun, int value)
{
TIMER *timer;
for (timer = ch->first_timer; timer; timer = timer->next)
if (timer->type == type)
{
timer->count = count;
timer->do_fun = fun;
timer->value = value;
break;
}
if (!timer)
{
CREATE(timer, TIMER, 1);
timer->count = count;
timer->type = type;
timer->do_fun = fun;
timer->value = value;
LINK(timer, ch->first_timer, ch->last_timer, next, prev);
}
}
void add_obj_timer( OBJ_DATA *obj, sh_int type, sh_int count, DO_FUN *fun, int value )
{
TIMER *timer;
for ( timer = obj->first_timer; timer; timer = timer->next )
if ( timer->type == type )
{
timer->count = count;
timer->do_fun = fun;
timer->value = value;
break;
}
if ( !timer )
{
CREATE( timer, TIMER, 1 );
timer->count = count;
timer->type = type;
timer->do_fun = fun;
timer->value = value;
LINK( timer, obj->first_timer, obj->last_timer, next, prev );
}
}
TIMER *get_timerptr(CHAR_DATA * ch, sh_int type)
{
TIMER *timer;
for (timer = ch->first_timer; timer; timer = timer->next)
if (timer->type == type)
return timer;
return NULL;
}
TIMER *get_obj_timerptr( OBJ_DATA *obj, sh_int type )
{
TIMER *timer;
for ( timer = obj->first_timer; timer; timer = timer->next )
if ( timer->type == type )
return timer;
return NULL;
}
sh_int get_timer(CHAR_DATA * ch, sh_int type)
{
TIMER *timer;
if ((timer = get_timerptr(ch, type)) != NULL)
return timer->count;
else
return 0;
}
sh_int get_obj_timer( OBJ_DATA *obj, sh_int type )
{
TIMER *timer;
if ( (timer = get_obj_timerptr( obj, type )) != NULL )
return timer->count;
else
return 0;
}
void extract_timer(CHAR_DATA * ch, TIMER * timer)
{
if (!timer)
{
bug("extract_timer: NULL timer", 0);
return;
}
UNLINK(timer, ch->first_timer, ch->last_timer, next, prev);
DISPOSE(timer);
return;
}
void extract_obj_timer( OBJ_DATA *obj, TIMER *timer )
{
if ( !timer )
{
bug( "extract_timer: NULL timer", 0 );
return;
}
separate_obj(obj);
UNLINK( timer, obj->first_timer, obj->last_timer, next, prev );
DISPOSE( timer );
return;
}
void remove_timer(CHAR_DATA * ch, sh_int type)
{
TIMER *timer;
for (timer = ch->first_timer; timer; timer = timer->next)
if (timer->type == type)
break;
if (timer)
extract_timer(ch, timer);
}
void remove_obj_timer( OBJ_DATA *obj, sh_int type )
{
TIMER *timer;
for ( timer = obj->first_timer; timer; timer = timer->next )
if ( timer->type == type )
break;
if ( timer )
extract_obj_timer( obj, timer );
}
bool in_soft_range(CHAR_DATA * ch, AREA_DATA * tarea)
{
if (IS_IMMORTAL(ch))
return TRUE;
else if (IS_NPC(ch))
return TRUE;
else if (ch->level >= tarea->low_soft_range || ch->level <= tarea->hi_soft_range)
return TRUE;
else
return FALSE;
}
bool can_astral(CHAR_DATA * ch, CHAR_DATA * victim)
{
if (victim == ch
|| !victim->in_room
|| xIS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
|| wIS_SET(victim, ROOM_PRIVATE)
|| xIS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
|| wIS_SET(victim, ROOM_SOLITARY)
|| xIS_SET(victim->in_room->room_flags, ROOM_NO_ASTRAL)
|| wIS_SET(victim, ROOM_NO_ASTRAL)
|| xIS_SET(victim->in_room->room_flags, ROOM_DEATH)
|| xIS_SET(ch->in_room->room_flags, ROOM_NO_RECALL)
|| (IS_NPC(victim) && xIS_SET(victim->act, ACT_PROTOTYPE)) || (IS_NPC(victim) && saves_spell_staff(ch->level, victim)))
return FALSE;
else
return TRUE;
}
bool in_hard_range(CHAR_DATA * ch, AREA_DATA * tarea)
{
if (IS_IMMORTAL(ch))
return TRUE;
else if (IS_NPC(ch))
return TRUE;
else if (ch->level >= tarea->low_hard_range && ch->level <= tarea->hi_hard_range)
return TRUE;
else
return FALSE;
}
/*
* Scryn, standard luck check 2/2/96
*/
bool chance(CHAR_DATA * ch, sh_int percent)
{
/* sh_int clan_factor, ms;*/
sh_int deity_factor, ms;
if (!ch)
{
bug("Chance: null ch!", 0);
return FALSE;
}
if (IS_DEVOTED(ch))
deity_factor = ch->pcdata->favor / -500;
else
deity_factor = 0;
ms = 10 - abs(ch->mental_state);
if ((number_percent() - get_curr_lck(ch) + 13 - ms) + deity_factor <= percent)
return TRUE;
else
return FALSE;
}
bool chance_attrib(CHAR_DATA * ch, sh_int percent, sh_int attrib)
{
/* Scryn, standard luck check + consideration of 1 attrib 2/2/96*/
sh_int deity_factor;
if (!ch)
{
bug("Chance: null ch!", 0);
return FALSE;
}
if (IS_DEVOTED(ch))
deity_factor = ch->pcdata->favor / -500;
else
deity_factor = 0;
if (number_percent() - get_curr_lck(ch) + 13 - attrib + 13 + deity_factor <= percent)
return TRUE;
else
return FALSE;
}
/*
* Make a simple clone of an object (no extras...yet) -Thoric
*/
OBJ_DATA *clone_object(OBJ_DATA * obj)
{
OBJ_DATA *clone;
EXTRA_DESCR_DATA *ed, *ced;
AFFECT_DATA *paf, *cpaf;
CREATE(clone, OBJ_DATA, 1);
clone->pIndexData = obj->pIndexData;
clone->name = QUICKLINK(obj->name);
clone->short_descr = QUICKLINK(obj->short_descr);
clone->description = QUICKLINK(obj->description);
clone->action_desc = QUICKLINK(obj->action_desc);
clone->item_type = obj->item_type;
clone->extra_flags = obj->extra_flags;
clone->magic_flags = obj->magic_flags;
clone->wear_flags = obj->wear_flags;
clone->wear_loc = obj->wear_loc;
clone->weight = obj->weight;
clone->cost = obj->cost;
clone->level = obj->level;
clone->timer = obj->timer;
clone->cident = obj->cident;
CREATE(clone->coord, COORD_DATA, 1);
clone->map = obj->map;
clone->coord->x = obj->coord->x;
clone->coord->y = obj->coord->y;
clone->value[0] = obj->value[0];
clone->value[1] = obj->value[1];
clone->value[2] = obj->value[2];
clone->value[3] = obj->value[3];
clone->value[4] = obj->value[4];
clone->value[5] = obj->value[5];
clone->value[6] = obj->value[6];
clone->value[7] = obj->value[7];
clone->value[8] = obj->value[8];
clone->value[9] = obj->value[9];
clone->value[10] = obj->value[10];
clone->value[11] = obj->value[11];
clone->value[12] = obj->value[12];
clone->value[13] = obj->value[13];
clone->count = 1;
for (ced = obj->first_extradesc; ced; ced = ced->next)
{
CREATE(ed, EXTRA_DESCR_DATA, 1);
ed->keyword = QUICKLINK(ced->keyword);
ed->description = QUICKLINK(ced->description);
LINK(ed, clone->first_extradesc, clone->last_extradesc, next, prev);
top_ed++;
}
for (cpaf = obj->first_affect; cpaf; cpaf = cpaf->next)
{
CREATE(paf, AFFECT_DATA, 1);
paf->type = cpaf->type;
paf->duration = cpaf->duration;
paf->location = cpaf->location;
paf->modifier = cpaf->modifier;
paf->bitvector = cpaf->bitvector;
LINK(paf, clone->first_affect, clone->last_affect, next, prev);
top_affect++;
}
++obj->pIndexData->count;
++numobjsloaded;
++physicalobjects;
cur_obj_serial = UMAX((cur_obj_serial + 1) & (BV30 - 1), 1);
clone->serial = clone->pIndexData->serial = cur_obj_serial;
LINK(clone, first_object, last_object, next, prev);
return clone;
}
/*
* If possible group obj2 into obj1 -Thoric
* This code, along with clone_object, obj->count, and special support
* for it implemented throughout handler.c and save.c should show improved
* performance on MUDs with players that hoard tons of potions and scrolls
* as this will allow them to be grouped together both in memory, and in
* the player files.
*/
OBJ_DATA *group_object(OBJ_DATA * obj1, OBJ_DATA * obj2)
{
if (!obj1 || !obj2)
return NULL;
if (obj1 == obj2)
return obj1;
if (obj1->pIndexData == obj2->pIndexData
/*
&& !obj1->pIndexData->mudprogs
&& !obj2->pIndexData->mudprogs
*/
&& QUICKMATCH(obj1->name, obj2->name)
&& QUICKMATCH(obj1->short_descr, obj2->short_descr)
&& QUICKMATCH(obj1->description, obj2->description)
&& QUICKMATCH(obj1->action_desc, obj2->action_desc)
&& obj1->item_type == obj2->item_type
&& xSAME_BITS(obj1->extra_flags, obj2->extra_flags)
&& obj1->magic_flags == obj2->magic_flags
&& obj1->wear_flags == obj2->wear_flags
&& obj1->wear_loc == obj2->wear_loc
&& obj1->weight == obj2->weight
&& obj1->cost == obj2->cost
&& obj1->level == obj2->level
&& obj1->timer == obj2->timer
&& obj1->value[0] == obj2->value[0]
&& obj1->value[1] == obj2->value[1]
&& obj1->value[2] == obj2->value[2]
&& obj1->value[3] == obj2->value[3]
&& obj1->value[4] == obj2->value[4]
&& obj1->value[5] == obj2->value[5]
&& obj1->value[6] == obj2->value[6]
&& obj1->value[7] == obj2->value[7]
&& obj1->value[8] == obj2->value[8]
&& obj1->value[9] == obj2->value[9]
&& obj1->value[10] == obj2->value[10]
&& obj1->value[11] == obj2->value[11]
&& obj1->value[12] == obj2->value[12]
&& obj1->value[13] == obj2->value[13]
&& !obj1->first_extradesc && !obj2->first_extradesc
&& !obj1->first_affect && !obj2->first_affect && !obj1->first_content && !obj2->first_content && obj1->count + obj2->count > 0 /* prevent count overflow */
&& obj1->map == obj2->map
&& obj1->coord->x == obj2->coord->x
&& obj1->coord->y == obj2->coord->y
&& !obj1->trap && !obj2->trap)
{
obj1->count += obj2->count;
obj1->pIndexData->count += obj2->count; /* to be decremented in */
numobjsloaded += obj2->count; /* extract_obj */
extract_obj(obj2);
return obj1;
}
return obj2;
}
/*
* Split off a grouped object -Thoric
* decreased obj's count to num, and creates a new object containing the rest
*/
OBJ_DATA *split_obj(OBJ_DATA * obj, int num)
{
int count = obj->count;
OBJ_DATA *rest;
if (count <= num || num == 0)
return NULL;
rest = clone_object(obj);
--obj->pIndexData->count; /* since clone_object() ups this value */
--numobjsloaded;
rest->count = obj->count - num;
obj->count = num;
if (obj->carried_by)
{
LINK(rest, obj->carried_by->first_carrying, obj->carried_by->last_carrying, next_content, prev_content);
rest->carried_by = obj->carried_by;
rest->possessed_by = obj->possessed_by;
rest->in_room = NULL;
rest->in_obj = NULL;
}
else if (obj->in_room)
{
LINK(rest, obj->in_room->first_content, obj->in_room->last_content, next_content, prev_content);
rest->carried_by = NULL;
rest->possessed_by = NULL;
rest->in_room = obj->in_room;
rest->in_obj = NULL;
}
else if (obj->in_obj)
{
LINK(rest, obj->in_obj->first_content, obj->in_obj->last_content, next_content, prev_content);
rest->in_obj = obj->in_obj;
rest->in_room = NULL;
rest->carried_by = NULL;
rest->possessed_by = NULL;
}
return rest;
}
OBJ_DATA *separate_obj(OBJ_DATA * obj)
{
return split_obj(obj, 1);
}
/*
* Empty an obj's contents... optionally into another obj, or a room
*/
bool empty_obj(OBJ_DATA * obj, OBJ_DATA * destobj, ROOM_INDEX_DATA * destroom)
{
OBJ_DATA *otmp, *otmp_next;
CHAR_DATA *ch = obj->carried_by;
bool movedsome = FALSE;
if (!obj)
{
bug("empty_obj: NULL obj", 0);
return FALSE;
}
if (destobj || (!destroom && !ch && (destobj = obj->in_obj) != NULL))
{
for (otmp = obj->first_content; otmp; otmp = otmp_next)
{
otmp_next = otmp->next_content;
/* only keys on a keyring */
if (destobj->item_type == ITEM_KEYRING && otmp->item_type != ITEM_KEY)
continue;
if (destobj->item_type == ITEM_QUIVER && otmp->item_type != ITEM_PROJECTILE)
continue;
if ((destobj->item_type == ITEM_CONTAINER || destobj->item_type == ITEM_KEYRING
|| destobj->item_type == ITEM_QUIVER) && get_real_obj_weight(otmp) + get_real_obj_weight(destobj) > destobj->value[0])
continue;
obj_from_obj(otmp);
obj_to_obj(otmp, destobj);
movedsome = TRUE;
}
return movedsome;
}
if (destroom || (!ch && (destroom = obj->in_room) != NULL))
{
for (otmp = obj->first_content; otmp; otmp = otmp_next)
{
otmp_next = otmp->next_content;
if (ch && HAS_PROG(otmp->pIndexData, DROP_PROG) && otmp->count > 1)
{
separate_obj(otmp);
obj_from_obj(otmp);
if (!otmp_next)
otmp_next = obj->first_content;
}
else
obj_from_obj(otmp);
otmp = obj_to_room(otmp, destroom, ch);
if (ch)
{
oprog_drop_trigger(ch, otmp); /* mudprogs */
if (char_died(ch))
ch = NULL;
}
movedsome = TRUE;
}
return movedsome;
}
if (ch)
{
for (otmp = obj->first_content; otmp; otmp = otmp_next)
{
otmp_next = otmp->next_content;
obj_from_obj(otmp);
obj_to_char(otmp, ch);
movedsome = TRUE;
}
return movedsome;
}
bug("empty_obj: could not determine a destination for vnum %d", obj->pIndexData->vnum);
return FALSE;
}
/*
* Improve mental state -Thoric
*/
void better_mental_state(CHAR_DATA * ch, int mod)
{
int c = URANGE(0, abs(mod), 20);
int con = get_curr_con(ch);
c += number_percent() < con ? 1 : 0;
if (ch->mental_state < 0)
ch->mental_state = URANGE(-100, ch->mental_state + c, 0);
else if (ch->mental_state > 0)
ch->mental_state = URANGE(0, ch->mental_state - c, 100);
}
/*
* Deteriorate mental state -Thoric
*/
void worsen_mental_state(CHAR_DATA * ch, int mod)
{
int c = URANGE(0, abs(mod), 20);
int con = get_curr_con(ch);
c -= number_percent() < con ? 1 : 0;
if (c < 1)
return;
/* Nuisance flag makes state worsen quicker. --Shaddai */
if (!IS_NPC(ch) && ch->pcdata->nuisance && ch->pcdata->nuisance->flags > 2)
c += .4 * ((ch->pcdata->nuisance->flags - 2) * ch->pcdata->nuisance->power);
if (ch->mental_state < 0)
ch->mental_state = URANGE(-100, ch->mental_state - c, 100);
else if (ch->mental_state > 0)
ch->mental_state = URANGE(-100, ch->mental_state + c, 100);
else
ch->mental_state -= c;
}
/*
* Add gold to an area's economy -Thoric
*/
void boost_economy(AREA_DATA * tarea, int gold)
{
while (gold >= 1000000000)
{
++tarea->high_economy;
gold -= 1000000000;
}
tarea->low_economy += gold;
while (tarea->low_economy >= 1000000000)
{
++tarea->high_economy;
tarea->low_economy -= 1000000000;
}
}
/*
* Take gold from an area's economy -Thoric
*/
void lower_economy(AREA_DATA * tarea, int gold)
{
while (gold >= 1000000000)
{
--tarea->high_economy;
gold -= 1000000000;
}
tarea->low_economy -= gold;
while (tarea->low_economy < 0)
{
--tarea->high_economy;
tarea->low_economy += 1000000000;
}
}
/*
* Check to see if economy has at least this much gold -Thoric
*/
bool economy_has(AREA_DATA * tarea, int gold)
{
int hasgold = ((tarea->high_economy > 0) ? 1 : 0) * 1000000000 + tarea->low_economy;
if (hasgold >= gold)
return TRUE;
return FALSE;
}
/*
* Used in db.c when resetting a mob into an area -Thoric
* Makes sure mob doesn't get more than 10% of that area's gold,
* and reduces area economy by the amount of gold given to the mob
*/
void economize_mobgold(CHAR_DATA * mob)
{
int gold;
AREA_DATA *tarea;
/* make sure it isn't way too much */
mob->gold = UMIN(mob->gold, 100000);
if (!mob->in_room)
return;
tarea = mob->in_room->area;
gold = ((tarea->high_economy > 0) ? 1 : 0) * 1000000000 + tarea->low_economy;
mob->gold = URANGE(0, mob->gold, gold / 10);
if (mob->gold)
lower_economy(tarea, mob->gold);
}
/*
* Add another notch on that there belt... ;)
* Keep track of the last so many kills by vnum -Thoric
*/
void add_kill(CHAR_DATA * ch, CHAR_DATA * mob)
{
int x;
sh_int vnum, track;
if (IS_NPC(ch))
{
bug("add_kill: trying to add kill to npc", 0);
return;
}
if (!IS_NPC(mob))
{
bug("add_kill: trying to add kill non-npc", 0);
return;
}
vnum = mob->pIndexData->vnum;
track = MAX_KILLTRACK;
for (x = 0; x < track; x++)
if (ch->pcdata->killed[x].vnum == vnum)
{
if (ch->pcdata->killed[x].count < 50)
++ch->pcdata->killed[x].count;
return;
}
else if (ch->pcdata->killed[x].vnum == 0)
break;
memmove((char *) ch->pcdata->killed + sizeof(KILLED_DATA), ch->pcdata->killed, (track - 1) * sizeof(KILLED_DATA));
ch->pcdata->killed[0].vnum = vnum;
ch->pcdata->killed[0].count = 1;
if (track < MAX_KILLTRACK)
ch->pcdata->killed[track].vnum = 0;
}
void update_pkpower(CHAR_DATA * ch)
{
//Boost the power if they reach a certain point
if (ch->pcdata->pranking >= 15 && ch->pcdata->pkpower < 1)
{
act(AT_RED, "$n flashes with a &BBlue&R Light as power flows through $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &BBlue&R Light pulsates throughout your vains.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower++;
ch->max_hit += 75;
ch->max_mana += 75;
ch->hit += 75;
ch->move += 75;
ch->mana += 75;
ch->perm_agi += 5;
}
if (ch->pcdata->pranking >= 35 && ch->pcdata->pkpower < 2)
{
act(AT_RED, "$n flashes with a &GGreen&R Light as power flows through $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &GGreen&R Light pulsates throughout your vains.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower++;
ch->max_hit += 100;
ch->max_mana += 100;
ch->hit += 100;
ch->move += 100;
ch->mana += 100;
ch->perm_agi += 10;
}
if (ch->pcdata->pranking >= 60 && ch->pcdata->pkpower < 3)
{
act(AT_RED, "$n flashes with a &G&WPURE WHITE&R Light as power flows through $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &G&WPURE WHITE&R Light pulsates throughout your vains.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower++;
ch->max_hit += 150;
ch->max_mana += 150;
ch->hit += 150;
ch->move += 150;
ch->mana += 150;
ch->perm_agi += 20;
}
//now take it away if they go below it
if (ch->pcdata->pranking < 15 && ch->pcdata->pkpower == 1)
{
act(AT_RED, "$n flashes with a &BBlue&R Light as power flows from $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &BBlue&R Light leaves your body.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower--;
ch->max_hit -= 75;
ch->max_mana -= 75;
ch->perm_agi -= 5;
}
if (ch->pcdata->pranking < 35 && ch->pcdata->pkpower == 2)
{
act(AT_RED, "$n flashes with a &GGreen&R Light as power flows from $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &GGreen&R Light leaves your body.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower--;
ch->max_hit -= 100;
ch->max_mana -= 100;
ch->perm_agi -= 10;
}
if (ch->pcdata->pranking < 60 && ch->pcdata->pkpower == 3)
{
act(AT_RED, "$n flashes with a &G&WPURE WHITE&R Light as power flows from $s vains.", ch, NULL, NULL, TO_CANSEE);
act(AT_RED, "Your body twitches as a &G&WPURE WHITE&R Light leaves your body.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower--;
ch->max_hit -= 150;
ch->max_mana -= 150;
ch->perm_agi -= 20;
}
//For those who just die a lot, zap them for a few, must be over level 20
if (ch->pcdata->pranking < -20 && ch->pcdata->pkpower >= 0)
{
act(AT_ORANGE, "$n flashes with a &rBLOOD RED&O as $e is punished for $s defeats.", ch, NULL, NULL, TO_CANSEE);
act(AT_ORANGE, "Your body shakes as a &rBLOOD RED&O Light enters your defeated body.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower--;
ch->max_hit -= 60;
ch->max_mana -= 60;
ch->perm_agi -= 15;
}
//Now just fix em
if (ch->pcdata->pranking >= -20 && ch->pcdata->pkpower == -1)
{
act(AT_ORANGE, "$n flashes with a &rBLOOD RED&O Light as the curse leaves $s body.", ch, NULL, NULL, TO_CANSEE);
act(AT_ORANGE, "Your body shakes as a &rBLOOD RED&O Light leaves your body.", ch, NULL, NULL, TO_CHAR);
ch->pcdata->pkpower++;
ch->max_hit += 60;
ch->max_mana += 60;
ch->perm_agi += 15;
ch->hit += 60;
ch->mana += 60;
}
}
//Update the pranking (pkill Ranking) for a kill
void update_pranking(CHAR_DATA * ch, CHAR_DATA * victim)
{
PKILLED_DATA *pkl;
int cnt = 0;
int camt, vamt, diff;
camt = vamt = 0;
//For now I don't want to add any pranking
return;
if (IN_ARENA(ch) || IN_ARENA(victim))
return;
camt = 1;
vamt = 1;
//Tack on an extra point for every 5 points of power difference
diff = victim->pcdata->pranking - ch->pcdata->pranking;
for (cnt = 5; cnt <= diff; cnt += 5)
{
camt++;
vamt++;
}
cnt = 0;
for (pkl = ch->pcdata->first_pkilled; pkl; pkl = pkl->next)
{
if (!str_cmp(pkl->name, victim->name))
cnt++;
}
if (cnt > 4)
camt = 0;
if (diff < -20)
camt = 0;
ch->pcdata->pranking += camt;
victim->pcdata->pranking -= vamt;
if (victim->pcdata->pranking < -30)
victim->pcdata->pranking = -30;
update_pkpower(ch);
update_pkpower(victim);
}
//Add the name of the victim to the pkill list on the player
void add_pkill(CHAR_DATA * ch, CHAR_DATA * victim)
{
PKILLED_DATA *pkl;
if (IS_NPC(victim))
{
bug("add_pkill: %s is trying to add %s to the pkill listing", ch->name, victim->name);
return;
}
if (IS_NPC(ch))
{
bug("add_pkill: %s is a NPC trying to add a PC to its listing", ch->name);
return;
}
if (ch->pcdata->pkilled < MAX_PKILLTRACK)
{
CREATE(pkl, PKILLED_DATA, 1);
pkl->name = STRALLOC(victim->name);
LINK(pkl, ch->pcdata->first_pkilled, ch->pcdata->last_pkilled, next, prev);
ch->pcdata->pkilled++;
}
else
{
pkl = ch->pcdata->first_pkilled;
UNLINK(pkl, ch->pcdata->first_pkilled, ch->pcdata->last_pkilled, next, prev);
STRFREE(pkl->name);
DISPOSE(pkl);
CREATE(pkl, PKILLED_DATA, 1);
pkl->name = STRALLOC(victim->name);
LINK(pkl, ch->pcdata->first_pkilled, ch->pcdata->last_pkilled, next, prev);
}
}
/*
* Return how many times this player has killed this mob -Thoric
* Only keeps track of so many (MAX_KILLTRACK), and keeps track by vnum
*/
int times_killed(CHAR_DATA * ch, CHAR_DATA * mob)
{
int x;
sh_int vnum, track;
if (IS_NPC(ch))
{
bug("times_killed: ch is not a player", 0);
return 0;
}
if (!IS_NPC(mob))
{
bug("add_kill: mob is not a mobile", 0);
return 0;
}
vnum = mob->pIndexData->vnum;
track = MAX_KILLTRACK;
for (x = 0; x < track; x++)
if (ch->pcdata->killed[x].vnum == vnum)
return ch->pcdata->killed[x].count;
else if (ch->pcdata->killed[x].vnum == 0)
break;
return 0;
}
/*
* returns area with name matching input string
* Last Modified : July 21, 1997
* Fireblade
*/
AREA_DATA *get_area(char *name)
{
AREA_DATA *pArea;
if (!name)
{
bug("get_area: NULL input string.");
return NULL;
}
for (pArea = first_area; pArea; pArea = pArea->next)
{
if (nifty_is_name(name, pArea->name))
break;
}
if (!pArea)
{
for (pArea = first_build; pArea; pArea = pArea->next)
{
if (nifty_is_name(name, pArea->name))
break;
}
}
return pArea;
}
/* Hometown Ivan Code -- Xerves */
int get_hometown(char *argument)
{
int i = 0;
while (i < sysdata.max_kingdom)
{
if (!str_cmp(argument, kingdom_table[i]->name))
return i;
i++;
}
return -1;
}