/*
* stats.c Phantasia routines player stat manipulation
*/
#include "include.h"
/************************************************************************
/
/ FUNCTION NAME: Do_init_player(struct client_t *c)
/
/ FUNCTION: initialize a character
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/ struct player *playerp - pointer to structure to init
/
/ RETURN VALUE: none
/
/ MODULES CALLED: floor(), drandom()
/
/ DESCRIPTION:
/ Put a bunch of default values in the given structure.
/
*************************************************************************/
Do_init_player(struct client_t *c)
{
c->player.name[0] =
c->player.lcname[0] =
c->modifiedName[0] =
c->player.password[0] =
c->player.area[0] = '\0';
c->player.last_load = 0;
/* initialize doubles */
c->player.x =
c->player.y =
c->player.circle =
c->player.brains =
c->player.magiclvl =
/* initialize floats */
c->player.poison =
c->player.sin =
/* initialize ints and shorts */
c->player.location =
c->player.age =
c->player.lives =
c->player.holywater =
c->player.amulets =
c->player.charms = 0;
/* initialize booleans */
c->player.beyond =
c->player.cloaked =
c->player.blind =
c->player.purgatoryFlag = FALSE;
c->player.gender = MALE;
/* specifics */
c->player.degenerated = 1; /* don't degenerate initially */
c->player.type = C_FIGHTER; /* default */
c->player.special_type = SC_NONE;
c->player.shield_nf =
c->player.haste_nf =
c->player.strong_nf = FALSE;
/* reset the client stat panel */
Do_name(c);
c->player.level = 0.0;
c->player.experience = 0.0;
Do_experience(c, 0.0, TRUE);
Do_energy(c, 0.0, 0.0, 0.0, 0.0, FALSE);
Do_strength(c, 0.0, 0.0, 0.0, FALSE);
Do_speed(c, 0.0, 0.0, 0.0, FALSE);
c->player.mana = 0.0;
Do_mana(c, 0.0, TRUE);
c->player.gold = 0.0;
Do_gold(c, 0.0, TRUE);
c->player.gems = 0.0;
Do_gems(c, 0.0, TRUE);
Do_cloak(c, FALSE, TRUE);
c->player.crowns = 0.0;
Do_crowns(c, 0, TRUE);
Do_blessing(c, FALSE, FALSE);
Do_palantir(c, FALSE, FALSE);
Do_virgin(c, FALSE, FALSE);
Do_ring(c, R_NONE, FALSE);
/* set user specific variables */
strcpy(c->player.parent_account, c->lcaccount);
strcpy(c->player.parent_network, c->network);
c->player.date_created = 0;
c->player.faithful = TRUE;
/* historic information */
c->player.bad_passwords =
c->player.muteCount =
c->player.load_count =
c->player.last_reset =
c->player.time_played = 0;
/* set a few client variables to false */
c->wizard =
c->stuck = FALSE;
/* specific client variables */
c->timeout = 120;
}
/************************************************************************
/
/ FUNCTION NAME: Do_update_stats(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 11/1/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_update_stats(struct client_t *c)
{
/* send the player's name */
Do_name(c);
Do_experience(c, 0.0, TRUE);
Do_energy(c, c->player.energy, c->player.max_energy, c->player.shield,
c->battle.force_field, TRUE);
Do_strength(c, c->player.max_strength, c->player.sword,
c->battle.strengthSpell, TRUE);
Do_speed(c, c->player.max_quickness, c->player.quicksilver,
c->battle.speedSpell, TRUE);
Do_mana(c, 0.0, TRUE);
Do_gold(c, 0.0, TRUE);
Do_gems(c, 0.0, TRUE);
Do_cloak(c, c->player.cloaked, TRUE);
Do_blessing(c, c->player.blessing, TRUE);
Do_crowns(c, 0, TRUE);
Do_palantir(c, c->player.palantir, TRUE);
Do_ring(c, c->player.ring_type, TRUE);
Do_virgin(c, c->player.virgin, TRUE);
}
/************************************************************************
/
/ FUNCTION NAME: Do_name(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_name(struct client_t *c)
{
/* send the name */
Do_send_int(c, NAME_PACKET);
Do_send_string(c, c->modifiedName);
Do_send_string(c, "\n");
Do_lock_mutex(&c->realm->realm_lock);
Do_location(c, c->player.x, c->player.y, TRUE);
Do_unlock_mutex(&c->realm->realm_lock);
}
/************************************************************************
/
/ FUNCTION NAME: Do_location(struct client_t *c, double x, double y)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_location(struct client_t *c, double x, double y, int force)
{
double distance;
/* Call this function with the realm locked if playing */
x = floor(x);
y = floor(y);
/* check for changes */
if (c->player.x != x || c->player.y != y || force) {
Do_distance(x, 0.0, y, 0.0, &distance);
c->player.circle = floor(distance / D_CIRCLE + 1);
c->player.x = x;
c->player.y = y;
Do_name_location(c);
Do_send_int(c, LOCATION_PACKET);
Do_send_double(c, x);
Do_send_double(c, y);
Do_send_string(c, c->player.area);
Do_send_string(c, "\n");
if (c->run_level == PLAY_GAME) {
c->game->x = x;
c->game->y = y;
c->game->circle = c->player.circle;
strncpy(c->game->area, c->player.area, SZ_AREA);
if (c->player.location == PL_REALM) {
c->game->useLocationName = FALSE;
}
else {
c->game->useLocationName = TRUE;
}
if (c->wizard > 2) {
c->game->virtual = TRUE;
}
else {
c->game->virtual = FALSE;
}
Do_player_description(c);
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_experience(struct client_t t, double theExpierence)
/
/ FUNCTION: move player to new level
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/16/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
/
/ GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
/
/ GLOBAL OUTPUTS: Player, Changed
/
/ DESCRIPTION:
/ Use lookup table to increment important statistics when
/ progressing to new experience level.
/ Players are rested to maximum as a bonus for making a new
/ level.
/ Check for council of wise, and being too big to be king.
/
*************************************************************************/
Do_experience(struct client_t *c, double theExperience, int force)
{
struct charstats_t *statptr; /* for pointing into Stattable */
struct event_t *event_ptr;
double new; /* new level */
double inc; /* increment between new and old levels */
char string_buffer[SZ_LINE];
/* add the experience */
c->player.experience += theExperience;
/* determine the new level */
new = CALCLEVEL(c->player.experience);
/*
if (c->player.experience < 1.1e7)
new = floor(pow((c->player.experience / 1000.0), 0.4748));
else
new = floor(pow((c->player.experience / 1250.0), 0.4865));
*/
inc = new - c->player.level;
/* if we've gone up any levels */
if (inc > 0) {
/* make sure we send the level information */
force = TRUE;
c->player.level = new;
if (c->player.type == C_EXPER)
/* roll a type to use for increment */
statptr = &c->realm->charstats[(int) ROLL(C_MAGIC,
(C_HALFLING - C_MAGIC + 1))];
else
statptr = &c->realm->charstats[c->player.type];
/* add increments to statistics */
Do_energy(c, c->player.energy + statptr->energy.increase * inc,
c->player.max_energy + statptr->energy.increase * inc,
c->player.shield, c->battle.force_field, FALSE);
Do_strength(c, c->player.max_strength + statptr->strength.increase
* inc, c->player.sword, c->battle.strengthSpell, FALSE);
Do_mana(c, statptr->mana.increase * inc, FALSE);
c->player.brains += statptr->brains.increase * inc;
c->player.magiclvl = c->player.magiclvl +
statptr->magiclvl.increase * inc;
/* knights may get more energy */
if (c->player.special_type == SC_KNIGHT) {
Do_energy(c, c->player.energy - c->knightEnergy +
floor(c->player.max_energy / 4), c->player.max_energy,
c->player.shield, c->battle.force_field, FALSE);
c->knightEnergy = floor(c->player.max_energy / 4);
}
if (c->player.level == 1000.0) {
/* send congratulations message */
Do_send_line(c, "Congratulations on reaching level 1000! The throne awaits...\n");
Do_more(c);
Do_send_clear(c);
}
if (c->player.level >= MAX_STEWARD &&
c->player.special_type == SC_STEWARD) {
/* no longer able to be steward -- dethrone */
Do_send_line(c,
"After level 200, you can no longer be steward.\n");
Do_dethrone(c);
}
if (c->player.level >= MAX_KING &&
c->player.special_type == SC_KING) {
/* no longer able to be king -- dethrone */
Do_send_line(c,
"After level 2000, you can no longer be king or queen.\n");
Do_dethrone(c);
c->player.special_type = SC_NONE;
}
/* see if staves/crowns should be cashed in */
if (c->player.crowns > 0) {
if (c->player.level >= MAX_KING) {
Do_send_line(c, "Your crowns were cashed in.\n");
Do_gold(c, (c->player.crowns) * 5000.0, FALSE);
Do_crowns(c, -(c->player.crowns), FALSE);
if (c->player.special_type == SC_KING) {
Do_dethrone(c);
}
Do_more(c);
Do_send_clear(c);
}
else if (c->player.level >= MAX_STEWARD && c->player.level < 1000.0) {
Do_send_line(c, "Your staves were cashed in.\n");
Do_gold(c, (c->player.crowns) * 1000.0, FALSE);
Do_crowns(c, -(c->player.crowns), FALSE);
if (c->player.special_type == SC_STEWARD) {
Do_dethrone(c);
}
Do_more(c);
Do_send_clear(c);
}
}
if (c->player.level >= 3000.0 && c->player.special_type < SC_COUNCIL) {
/* if by some chance this person is king or knight, dethrone him */
if (c->player.special_type == SC_KING || c->player.special_type == SC_KNIGHT) {
Do_dethrone(c);
}
/* announce the new member */
sprintf(string_buffer,
"The Council of the Wise announces its newest member, %s.\n",
c->modifiedName);
Do_broadcast(c, string_buffer);
/* make a member of the council */
Do_send_clear(c);
Do_send_line(c, "You have made it to the Council of the Wise.\n");
Do_send_line(c, "Good Luck on your search for the Holy Grail.\n");
c->player.special_type = SC_COUNCIL;
/* no rings for council and above */
Do_ring(c, R_NONE, FALSE);
c->player.lives = 2; /* two extra lives */
Do_send_specification(c, CHANGE_PLAYER_EVENT);
Do_more(c);
}
/* death from old age */
if ((c->player.level > 9999.0 - (10 * c->player.degenerated)) &&
(c->player.special_type != SC_VALAR)) {
event_ptr = (struct event_t *) Do_create_event();
event_ptr->type = DEATH_EVENT;
event_ptr->arg3 = K_OLD_AGE;
event_ptr->to = c->game;
Do_file_event(c, event_ptr);
}
/* player might gain some quickness */
Do_check_weight(c);
/* update player description */
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
Do_unlock_mutex(&c->realm->realm_lock);
/* recalculate the player's timeout */
if (c->wizard > 2) {
c->timeout = 900;
}
else if (c->player.level < 80) {
c->timeout = 60 - c->player.level / 2;
}
else {
c->timeout = 20;
}
/* log the increase */
sprintf(string_buffer, "%s, %s, %d age, %d seconds, level %0.0lf\n",
c->player.lcname,
c->realm->charstats[c->player.type].class_name,
c->player.age, c->player.time_played + time(NULL) -
c->player.last_load, c->player.level);
Do_log(LEVEL_LOG, &string_buffer);
/* backup up this character in case of crash */
Do_backup_save(c, TRUE);
}
if (force) {
/* send the level increase */
Do_send_int(c, LEVEL_PACKET);
Do_send_double(c, c->player.level);
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_energy(struct client_t *c, double energy, double maxEnergy, double shield)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_energy(struct client_t *c, double energy, double maxEnergy, double shield, double forceShield, int force)
{
maxEnergy = floor(maxEnergy);
shield = floor(shield);
energy = floor(energy);
forceShield = floor(forceShield);
if (maxEnergy < 0) {
maxEnergy = 0;
}
if (energy > maxEnergy + shield + c->knightEnergy) {
energy = maxEnergy + shield + c->knightEnergy;
}
/* check for changes */
if (c->player.energy != energy || c->player.max_energy != maxEnergy ||
c->player.shield != shield || c->battle.force_field !=
forceShield || force) {
Do_send_int(c, ENERGY_PACKET);
Do_send_double(c, energy);
Do_send_double(c, maxEnergy + shield + c->knightEnergy);
Do_send_double(c, forceShield);
c->player.energy = energy;
c->player.max_energy = maxEnergy;
c->battle.force_field = forceShield;
if (c->player.shield != shield || force) {
Do_send_int(c, SHIELD_PACKET);
Do_send_double(c, shield);
c->player.shield = shield;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_strength(struct client_t *c, double strength, double maxStrength, double sword, double strengthSpell)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_strength(struct client_t *c, double maxStrength, double sword, double strengthSpell, int force)
{
double strength;
/* a player can have a minimum of 0 strength */
if (maxStrength < 0) {
maxStrength = 0;
}
/* calculate strength based on poison */
strength = 1.0 - c->player.poison *
c->realm->charstats[c->player.type].weakness / 800.0;
if (strength > 1.0) {
strength = 1.0;
}
if (strength < .1) {
strength = .1;
}
strength = maxStrength * strength;
/* check for changes */
if (c->player.strength != strength || c->player.max_strength !=
maxStrength || c->player.sword != sword || c->battle.strengthSpell
!= strengthSpell || force) {
Do_send_int(c, STRENGTH_PACKET);
Do_send_double(c, strength * (1 + sqrt(sword) * N_SWORDPOWER) + strengthSpell);
Do_send_double(c, maxStrength * (1 + sqrt(sword) * N_SWORDPOWER) + strengthSpell);
c->player.strength = strength;
c->player.max_strength = maxStrength;
c->battle.strengthSpell = strengthSpell;
if (c->player.sword != sword || force) {
Do_send_int(c, SWORD_PACKET);
Do_send_double(c, sword);
c->player.sword = sword;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_speed(struct client_t *c, double maxQuickness, double quicksilver, double speedSpell, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_speed(struct client_t *c, double maxQuickness, double quicksilver, double speedSpell, int force)
{
double dtemp;
double quickness;
/* a player can have a minimum of 0 quickness */
if (maxQuickness < 0.0) {
maxQuickness = 0.0;
}
/* see if the player is carrying too much treasure */
if (c->wizard < 3) {
dtemp = ((c->player.gold + c->player.gems / 2.0) - 1000.0) /
c->realm->charstats[c->player.type].goldtote - c->player.level;
} else {
dtemp = 0.0;
}
/* gold can only slow a player down */
if (dtemp < 0.0) {
dtemp = 0.0;
}
/* subtract speed for excessive combat */
dtemp += c->battle.rounds / N_FATIGUE;
quickness = maxQuickness + sqrt(floor(quicksilver)) + speedSpell +
c->knightQuickness - dtemp;
if (quickness < 0.0) {
quickness = 0.0;
}
/* check for changes */
if (c->player.quickness != quickness || c->player.max_quickness !=
maxQuickness || c->player.quicksilver != quicksilver ||
c->battle.speedSpell != speedSpell || force) {
Do_send_int(c, SPEED_PACKET);
Do_send_double(c, quickness);
Do_send_double(c, maxQuickness + sqrt(floor(quicksilver)) + speedSpell +
c->knightQuickness);
c->player.quickness = quickness;
c->player.max_quickness = maxQuickness;
c->battle.speedSpell = speedSpell;
if (c->player.quicksilver != quicksilver || force) {
Do_send_int(c, QUICKSILVER_PACKET);
Do_send_float(c, quicksilver);
c->player.quicksilver = quicksilver;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_mana(struct client_t *c, double mana)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_mana(struct client_t *c, double mana, int force)
{
double newMana;
double maxMana;
char error_msg[SZ_ERROR_MESSAGE];
/* make sure we're still under the maximum mana */
newMana = floor(c->player.mana + mana);
maxMana = 1000.0 + c->player.level *
c->realm->charstats[c->player.type].max_mana;
if (newMana > maxMana) {
newMana = maxMana;
}
if (newMana != c->player.mana || force) {
c->player.mana = newMana;
Do_send_int(c, MANA_PACKET);
Do_send_double(c, c->player.mana);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_gold(struct client_t *c, double gold)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/2/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_gold(struct client_t *c, double gold, int force)
{
double dtemp;
if (gold != 0) {
force = TRUE;
/* all gold is taxed to drain the economy */
/*
if (gold > 0) {
dtemp = floor(gold / (15 + c->player.level));
gold -= dtemp;
if (dtemp > 0) {
Do_lock_mutex(&c->realm->kings_gold_lock);
c->realm->kings_gold += dtemp;
Do_unlock_mutex(&c->realm->kings_gold_lock);
}
}
*/
/* make sure we never end up with negative gold */
if (c->player.gold + gold > 0)
c->player.gold = floor(c->player.gold + gold);
else
c->player.gold = 0;
Do_check_weight(c);
}
if (force) {
Do_send_int(c, GOLD_PACKET);
Do_send_double(c, c->player.gold);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_gems(struct client_t *c, double gems)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_gems(struct client_t *c, double gems, int force)
{
double dtemp;
if (gems != 0) {
force = TRUE;
/*
if (gems > 0) {
dtemp = floor(gems / (15 + c->player.level));
gems -= dtemp;
if (dtemp > 0) {
Do_lock_mutex(&c->realm->kings_gold_lock);
c->realm->kings_gold += dtemp * N_GEMVALUE;
Do_unlock_mutex(&c->realm->kings_gold_lock);
}
}
*/
/* make sure we never end up with negative gems */
if (c->player.gems + gems > 0)
c->player.gems = floor(c->player.gems + gems);
else
c->player.gems = 0;
Do_check_weight(c);
}
if (force) {
Do_send_int(c, GEMS_PACKET);
Do_send_double(c, c->player.gems);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_cloak(struct client_t *c)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/16/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getans
wer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_cloak(struct client_t *c, int state, int force)
{
struct realm_object_t *object_ptr, **object_ptr_ptr;
struct event_t *event_ptr;
char error_msg[SZ_ERROR_MESSAGE];
/* if this state is a change */
if (state != c->player.cloaked) {
force = TRUE;
/* if we're cloaking */
if (state) {
if (c->player.mana < MM_CLOAK) {
Do_send_line(c, "No mana left.\n");
Do_more(c);
return;
}
else {
c->player.cloaked = TRUE;
c->player.mana -= MM_CLOAK;
}
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
Do_unlock_mutex(&c->realm->realm_lock);
} else {
Do_lock_mutex(&c->realm->realm_lock);
/* check for realm objects in the new location */
object_ptr_ptr = &c->realm->objects;
while(*object_ptr_ptr != NULL) {
if ((*object_ptr_ptr)->x == c->player.x && (*object_ptr_ptr)->y
== c->player.y) {
object_ptr = *object_ptr_ptr;
*object_ptr_ptr = object_ptr->next_object;
event_ptr = (struct event_t *) Do_create_event();
switch (object_ptr->type) {
case CORPSE:
event_ptr->type = CORPSE_EVENT;
/* the corpse can be cursed */
event_ptr->arg1 = TRUE;
event_ptr->arg4 = object_ptr->arg1;
break;
case HOLY_GRAIL:
event_ptr->type = NULL_EVENT;
/* don't give the grail to
a player who uncloaks on it */
Do_send_line(c, "You found the Grail! But you were cloaked...\n");
Do_more(c);
Do_hide_grail(c->realm, c->player.level);
break;
case ENERGY_VOID:
event_ptr->type = ENERGY_VOID_EVENT;
break;
case TREASURE_TROVE:
event_ptr->type = TROVE_EVENT;
Do_hide_trove(c->realm);
break;
default:
sprintf(error_msg,
"[%s] encountered realm object of type %d in Do_cloak.\n",
c->connection_id, object_ptr->type);
Do_log_error(error_msg);
}
if (event_ptr->type != NULL_EVENT) {
Do_file_event(c, event_ptr);
} else {
free((void *)event_ptr);
}
free((void *)object_ptr);
} else {
object_ptr_ptr = &((*object_ptr_ptr)->next_object);
}
}
Do_unlock_mutex(&c->realm->realm_lock);
}
}
c->player.cloaked = state;
if (force) {
Do_send_int(c, CLOAK_PACKET);
Do_send_bool(c, c->player.cloaked);
}
return;
}
/************************************************************************
/
/ FUNCTION NAME: Do_crowns(struct client_t *c, int crowns)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_crowns(struct client_t *c, int crowns, int force)
{
bool crownFlag;
crownFlag = ANY(c->player.crowns);
if (crowns != 0) {
c->player.crowns = c->player.crowns + crowns;
if (c->player.crowns < 0) {
c->player.crowns = 0.0;
}
if (crownFlag != ANY(c->player.crowns)) {
crownFlag = !crownFlag;
force = TRUE;
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
Do_unlock_mutex(&c->realm->realm_lock);
}
}
if (force) {
Do_send_int(c, CROWN_PACKET);
Do_send_bool(c, crownFlag);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_blessing(struct client_t *c, bool blessing)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_blessing(struct client_t *c, int blessing, int force)
{
if (blessing != c->player.blessing || force) {
Do_send_int(c, BLESSING_PACKET);
Do_send_bool(c, blessing);
c->player.blessing = blessing;
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_palantir(struct client_t *c, bool palantir, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_palantir(struct client_t *c, int palantir, int force)
{
if (palantir != c->player.palantir || force) {
Do_send_int(c, PALANTIR_PACKET);
Do_send_bool(c, palantir);
c->player.palantir = palantir;
}
/* if no palantir, kick player out of the palantir channel */
if ((c->player.palantir == FALSE) &&
(c->channel == 8)) {
c->channel = 1;
c->game->hearAllChannels = HEAR_SELF;
Do_lock_mutex(&c->realm->realm_lock);
Do_player_description(c);
Do_unlock_mutex(&c->realm->realm_lock);
Do_send_specification(c, CHANGE_PLAYER_EVENT);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_virgin(struct client_t *c, bool virgin)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_virgin(struct client_t *c, int virgin, int force)
{
if (virgin != c->player.virgin || force) {
Do_send_int(c, VIRGIN_PACKET);
Do_send_bool(c, virgin);
c->player.virgin = virgin;
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_ring(struct client_t *c, int ring, int force)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_ring(struct client_t *c, int ring, int force)
{
bool ringFlag;
switch (ring) {
case R_NONE:
if (c->player.ring_type != R_NONE) {
c->player.ring_type = R_NONE;
force = TRUE;
}
ringFlag = FALSE;
break;
case R_NAZREG:
if (c->player.ring_type == R_NONE) {
c->player.ring_type = R_NAZREG;
c->player.ring_duration = RND() * RND() * 150 + 1;
force = TRUE;
}
ringFlag = TRUE;
break;
case R_DLREG:
if (c->player.ring_type == R_NONE) {
c->player.ring_type = R_DLREG;
c->player.ring_duration = 0;
force = TRUE;
}
ringFlag = TRUE;
break;
case R_BAD:
if (c->player.ring_type == R_NONE) {
c->player.ring_type = R_BAD;
c->player.ring_duration = 15 +
c->realm->charstats[c->player.type].ring_duration +
(int) ROLL (0,5);
force = TRUE;
}
ringFlag = TRUE;
break;
case R_SPOILED:
if (c->player.ring_type == R_BAD) {
c->player.ring_type = R_SPOILED;
c->player.ring_duration = ROLL(10.0, 25.0);
}
ringFlag = TRUE;
break;
}
if (force) {
Do_send_int(c, RING_PACKET);
Do_send_bool(c, ringFlag);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_charm(struct client_t *c, int charms)
/
/ FUNCTION: do trading post stuff
/
/ AUTHOR: Brian Kelly, 10/3/99
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: writerecord(), adjuststats(), fabs(), more(), sqrt(),
/ sleep(), floor(), wmove(), drandom(), wclear(), printw(),
/ altercoordinates(), infloat(), waddstr(), wrefresh(), mvprintw(), getanswer(),
/ wclrtoeol(), wclrtobot()
/
/ DESCRIPTION:
/
*************************************************************************/
Do_charm(struct client_t *c, int charms)
{
/* make sure we're still under the maximum charms */
c->player.charms = MIN(c->player.charms + charms, c->player.level + 10.0);
}
/***************************************************************************
/ FUNCTION NAME: Do_age(struct client_t *c)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 6/17/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_age(struct client_t *c)
{
struct event_t *event_ptr;
double temp;
/* take hit points if player has poison */
if (c->player.poison > 0.0) {
temp = c->player.poison * c->realm->charstats[c->player.type].weakness
* c->player.max_energy / 600.0;
/* Removed bit that prevents energy loss for large poison values
if (c->player.energy > c->player.max_energy / 10.0 && temp + 5.0 <
c->player.energy) {
*/
if (c->player.energy > (c->player.max_energy + c->player.shield)
/ 10.0) {
/* Thrown in so sick energy can't drop below 10% */
temp = MIN(temp, c->player.energy - (c->player.max_energy +
c->player.shield) / 10.0);
Do_energy(c, c->player.energy - temp, c->player.max_energy,
c->player.shield, c->battle.force_field, FALSE);
}
}
/* if cloaked, remove mana */
if (c->player.cloaked) {
if ((c->player.circle == 27) || (c->player.circle == 28)) {
temp = floor(.02 * (1000 + c->player.level *
c->realm->charstats[c->player.type].max_mana));
} else if ((c->player.circle > 24) && (c->player.circle < 31)) {
temp = floor(.01 * (1000 + c->player.level *
c->realm->charstats[c->player.type].max_mana));
} else if ((c->player.circle > 19) && (c->player.circle < 36)) {
temp = floor(.005 * (1000 + c->player.level *
c->realm->charstats[c->player.type].max_mana));
} else {
temp = c->player.circle;
}
if (c->player.mana >= temp)
Do_mana(c, -temp, FALSE);
else {
Do_send_line(c,
"You do not have enough mana to sustain your cloak.\n");
/* ran out of mana, uncloak */
event_ptr = (struct event_t *) Do_create_event();
event_ptr->type = CLOAK_EVENT;
Do_handle_event(c, event_ptr);
}
}
/* Check if the Knight should stick around */
if(c->player.special_type == SC_KNIGHT && c->realm->king == NULL){
Do_dethrone(c);
}
/* Count out aging every other turn if you are holding the One Ring */
if (c->player.ring_type == R_DLREG){
c->ageCount++;
if (c->ageCount == 2){
c->player.age++;
c->ageCount = 0;
} else {
c->player.age++;
}
} else {
c->player.age++;
c->morgothCount--;
if(c->morgothCount < 0){
c->morgothCount = 0;
}
}
while (c->player.age / N_AGE > c->player.degenerated && (c->wizard < 3)) {
Do_degenerate(c, TRUE);
}
}
/***************************************************************************
/ FUNCTION NAME: Do_poison_modifier(struct client_t *c, float poison)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 5/6/01
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_adjusted_poison(struct client_t *c, double poison)
{
double dtemp;
dtemp = c->player.circle - 17;
poison *= (SGN(dtemp) * pow(fabs(dtemp), .33) + 5.52) / 3;
Do_poison(c, poison);
}
/***************************************************************************
/ FUNCTION NAME: Do_poison(struct client_t *c, double poison)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 10/10/99
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_poison(struct client_t *c, double poison)
{
if (poison != 0) {
c->player.poison += poison;
if (c->player.poison < 1e-4) {
c->player.poison = 0.0;
}
Do_strength(c, c->player.max_strength, c->player.sword,
c->battle.strengthSpell, FALSE);
}
}
/***************************************************************************
/ FUNCTION NAME: Do_sin(struct client_t *c, float *sin)
/
/ FUNCTION: Default activity when no events are pending
/
/ AUTHOR: Brian Kelly, 06/15/01
/
/ ARGUMENTS:
/ struct client_t *c - structure containing all thread info
/
/ RETURN VALUE: none
/
/ DESCRIPTION:
/ Process arguments, initialize program, and loop forever processing
/ player input.
/
****************************************************************************/
Do_sin(struct client_t *c, double sin)
{
struct event_t *event_ptr;
if (isnan(c->player.sin)) {
c->player.sin = 0.0;
}
/* Doubles any ammount of sin you take in while carrying the one ring */
if (c->player.ring_type == R_DLREG){
c->player.sin += sin*2;
} else {
c->player.sin += sin;
}
if (c->player.sin < 0.0) {
c->player.sin = 0.0;
}
if (c->player.blessing && c->player.sin > (1500.0 + c->player.level) /
(c->player.level + 30.0)) {
Do_send_line(c,
"Your blessing is consumed by the evil of your actions!\n");
Do_more(c);
Do_send_clear(c);
Do_blessing(c, FALSE, FALSE);
}
if (c->player.sin > 25.0 + RND() * 25.0) {
event_ptr = (struct event_t *)Do_create_event();
event_ptr->type = DEATH_EVENT;
event_ptr->arg3 = K_SIN;
Do_file_event(c, event_ptr);
} else if ((c->player.sin > 20.0) && (RND() < .2)) {
Do_send_line(c,
"You cackle gleefully at the chaos you are causing!\n");
Do_more(c);
Do_send_clear(c);
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_book(struct client_t *c, int bookCount)
/
/ FUNCTION: initialize a character
/
/ AUTHOR: E. A. Estes, 12/4/85
/ Brian Kelly, 5/4/99
/
/ ARGUMENTS:
/ struct player *playerp - pointer to structure to init
/
/ RETURN VALUE: none
/
/ MODULES CALLED: floor(), drandom()
/
/ DESCRIPTION:
/ Put a bunch of default values in the given structure.
/
*************************************************************************/
Do_book(struct client_t *c, int bookCount)
{
int i, multiple;
float ftemp;
double dtemp1, dtemp2;
for (i = 0; i < bookCount; i++) {
ftemp = c->player.brains - c->player.level *
c->realm->charstats[c->player.type].max_brains;
multiple = ceil(ftemp / (c->player.level *
c->realm->charstats[c->player.type].max_brains));
dtemp1 = c->realm->charstats[c->player.type].brains.increase;
/* make it really hard to get more than max brains */
if (ftemp > 0) {
if (multiple > 0) {
dtemp2 = dtemp1 * (dtemp1 - 1) / multiple;
} else {
dtemp2 = dtemp1 * (dtemp1 - 1);
}
c->player.brains += dtemp2 / sqrt(ftemp + dtemp2);
} else {
c->player.brains += dtemp1 / 2;
}
}
}
/************************************************************************
/
/ FUNCTION NAME: Do_forceage(struct client_t t, double Degens)
/
/ FUNCTION: forcefully age a player
/
/ AUTHOR: Arella Kirstar 7/4/02
/
/ ARGUMENTS: none
/
/ RETURN VALUE: none
/
/ MODULES CALLED: death(), floor(), wmove(), drandom(), waddstr(), explevel()
/
/ GLOBAL INPUTS: Player, *stdscr, *Statptr, Stattable[]
/
/ GLOBAL OUTPUTS: Player, Changed
/
/ DESCRIPTION:
/ Used to forcefully add degenerations and age to a player
/
*************************************************************************/
Do_forceage(struct client_t *c, double Degens)
{
struct event_t *event_ptr;
char string_buffer[SZ_LINE];
/* add the degens and age */
c->player.degenerated = Degens;
c->player.age = Degens * 750;
}