예제 #1
0
int cast_cure_disease(string str) {
  int skill;
  mixed ret;
 
  str = (string)this_player()->expand_nickname(str);
  skill = (int)this_player()->query_skill("faith.spells.curing.target");
  if (skill<MIN_LVL) {
    notify_fail("You are not skillful enough.\n");
    return 0;
  }
  skill = (int)this_player()->query_skill_bonus("faith.spells.defensive.target");
  ret = cure_disease(str, skill, 1);
  if (stringp(ret)) {
    notify_fail(ret);
    return 0;
  }
  write("You cast Cure disease.\n");
  return 1;
}
예제 #2
0
파일: player.c 프로젝트: atrinik/dwc
/**
 * If the player should die (lack of hp, food, etc), we call this.
 *
 * Will remove diseases, apply death penalties, and so on.
 * @param op The player in jeopardy. */
void kill_player(object *op)
{
	char buf[HUGE_BUF];
	int x, y, i;
	/* this is for resurrection */
	mapstruct *map;
	object *tmp;
	int z;
	int num_stats_lose;
	int lost_a_stat;
	int lose_this_stat;
	int this_stat;

	if (pvp_area(NULL, op))
	{
		new_draw_info(NDI_UNIQUE | NDI_NAVY, op, "You have been defeated in combat!");
		new_draw_info(NDI_UNIQUE | NDI_NAVY, op, "Local medics have saved your life...");

		/* Restore player */
		cast_heal(op, MAXLEVEL, op, SP_CURE_POISON);
		/* Remove any disease */
		cure_disease(op, NULL);
		op->stats.hp = op->stats.maxhp;

		if (op->stats.food <= 0)
		{
			op->stats.food = 999;
		}

		/* Create a bodypart-trophy to make the winner happy */
		tmp = arch_to_object(find_archetype("finger"));

		if (tmp != NULL)
		{
			char race[MAX_BUF];

			snprintf(buf, sizeof(buf), "%s's finger", op->name);
			FREE_AND_COPY_HASH(tmp->name, buf);
			snprintf(buf, sizeof(buf), "This finger has been cut off %s the %s, when %s was defeated at level %d by %s.", op->name, player_get_race_class(op, race, sizeof(race)), gender_subjective[object_get_gender(op)], op->level, CONTR(op)->killer[0] == '\0' ? "something nasty" : CONTR(op)->killer);
			FREE_AND_COPY_HASH(tmp->msg, buf);
			tmp->value = 0, tmp->material = 0, tmp->type = 0;
			tmp->x = op->x, tmp->y = op->y;
			insert_ob_in_map(tmp, op->map, op, 0);
		}

		/* Teleport defeated player to new destination */
		transfer_ob(op, MAP_ENTER_X(op->map), MAP_ENTER_Y(op->map), 0, NULL, NULL);
		return;
	}

	if (save_life(op))
	{
		return;
	}

	/* Trigger the DEATH event */
	if (trigger_event(EVENT_DEATH, NULL, op, NULL, NULL, 0, 0, 0, SCRIPT_FIX_ALL))
	{
		return;
	}

	/* Trigger the global GDEATH event */
	trigger_global_event(EVENT_GDEATH, NULL, op);

	play_sound_player_only(CONTR(op), SOUND_PLAYER_DIES, SOUND_NORMAL, 0, 0);

	/* Save the map location for corpse, gravestone */
	x = op->x;
	y = op->y;
	map = op->map;

	/* Basically two ways to go - remove a stat permanently, or just
	 * make it depletion.  This bunch of code deals with that aspect
	 * of death. */
	if (settings.balanced_stat_loss)
	{
		/* If stat loss is permanent, lose one stat only. */
		/* Lower level chars don't lose as many stats because they suffer more
		   if they do. */
		if (settings.stat_loss_on_death)
		{
			num_stats_lose = 1;
		}
		else
		{
			num_stats_lose = 1 + op->level / BALSL_NUMBER_LOSSES_RATIO;
		}
	}
	else
	{
		num_stats_lose = 1;
	}

	lost_a_stat = 0;

	/* Only decrease stats if you are level 3 or higher. */
	for (z = 0; z < num_stats_lose; z++)
	{
		if (settings.stat_loss_on_death && op->level > 3)
		{
			/* Pick a random stat and take a point off it. Tell the
			 * player what he lost. */
			i = rndm(1, NUM_STATS) - 1;
			change_attr_value(&(op->stats), i, -1);
			check_stat_bounds(&(op->stats));
			change_attr_value(&(CONTR(op)->orig_stats), i, -1);
			check_stat_bounds(&(CONTR(op)->orig_stats));
			new_draw_info(NDI_UNIQUE, op, lose_msg[i]);
			lost_a_stat = 1;
		}
		else if (op->level > 3)
		{
			/* Deplete a stat */
			archetype *deparch = find_archetype("depletion");
			object *dep;

			i = rndm(1, NUM_STATS) - 1;
			dep = present_arch_in_ob(deparch, op);

			if (!dep)
			{
				dep = arch_to_object(deparch);
				insert_ob_in_ob(dep, op);
			}

			lose_this_stat = 1;

			if (settings.balanced_stat_loss)
			{
				/* Get the stat that we're about to deplete. */
				this_stat = get_attr_value(&(dep->stats), i);

				if (this_stat < 0)
				{
					int loss_chance = 1 + op->level / BALSL_LOSS_CHANCE_RATIO;
					int keep_chance = this_stat * this_stat;

					/* Yes, I am paranoid. Sue me. */
					if (keep_chance < 1)
					{
						keep_chance = 1;
					}

					/* There is a maximum depletion total per level. */
					if (this_stat < -1 - op->level / BALSL_MAX_LOSS_RATIO)
					{
						lose_this_stat = 0;
					}
					else
					{
						/* Take loss chance vs keep chance to see if we retain the stat. */
						if (rndm(0, loss_chance + keep_chance - 1) < keep_chance)
						{
							lose_this_stat = 0;
						}
					}
				}
			}

			if (lose_this_stat)
			{
				this_stat = get_attr_value(&(dep->stats), i);

				/* We could try to do something clever like find another
				 * stat to reduce if this fails.  But chances are, if
				 * stats have been depleted to -50, all are pretty low
				 * and should be roughly the same, so it shouldn't make a
				 * difference. */
				if (this_stat >= -50)
				{
					change_attr_value(&(dep->stats), i, -1);
					SET_FLAG(dep, FLAG_APPLIED);
					new_draw_info(NDI_UNIQUE, op, lose_msg[i]);
					fix_player(op);
					lost_a_stat = 1;
				}
			}
		}
	}

	/* If no stat lost, tell the player. */
	if (!lost_a_stat)
	{
		const char *god = determine_god(op);

		if (god && god != shstr_cons.none)
		{
			new_draw_info_format(NDI_UNIQUE, op, "For a brief moment you feel the holy presence of %s protecting you.", god);
		}
		else
		{
			new_draw_info(NDI_UNIQUE, op, "For a brief moment you feel a holy presence protecting you.");
		}
	}

	/* Put a gravestone up where the character 'almost' died. */
	tmp = arch_to_object(find_archetype("gravestone"));
	snprintf(buf, sizeof(buf), "%s's gravestone", op->name);
	FREE_AND_COPY_HASH(tmp->name, buf);
	FREE_AND_COPY_HASH(tmp->msg, gravestone_text(op));
	tmp->x = op->x, tmp->y = op->y;
	insert_ob_in_map(tmp, op->map, NULL, 0);

	/* Subtract the experience points, if we died because of food give us
	 * food, and reset HP... */

	/* Remove any poisoning the character may be suffering. */
	cast_heal(op, MAXLEVEL, op, SP_CURE_POISON);
	/* Remove any disease */
	cure_disease(op, NULL);

	/* Apply death experience penalty. */
	apply_death_exp_penalty(op);

	if (op->stats.food < 0)
	{
		op->stats.food = 900;
	}

	op->stats.hp = op->stats.maxhp;
	op->stats.sp = op->stats.maxsp;
	op->stats.grace = op->stats.maxgrace;

	hiscore_check(op, 1);

	/* Otherwise the highscore can get entries like 'xxx was killed by pudding
	 * on map Wilderness' even if they were killed in a dungeon. */
	CONTR(op)->killer[0] = '\0';

	/* Check to see if the player is in a shop. Ii so, then check to see
	 * if the player has any unpaid items. If so, remove them and put
	 * them back in the map. */
	tmp = get_map_ob(op->map, op->x, op->y);

	if (tmp && tmp->type == SHOP_FLOOR)
	{
		remove_unpaid_objects(op->inv, op);
	}

	/* Move player to his current respawn position (last savebed). */
	enter_player_savebed(op);

	/* Show a nasty message */
	new_draw_info(NDI_UNIQUE, op, "YOU HAVE DIED.");
	save_player(op, 1);
	return;
}