Beispiel #1
0
/*
 * Alert: As of bpl14, this function returns the following codes:
 *	< 0	Victim died.
 *	= 0	No damage.
 *	> 0	How much damage done.
 */
int damage(struct char_data *ch, struct char_data *victim, int dam, int attacktype)
{
  if (GET_POS(victim) <= POS_DEAD) {
    /* This is "normal"-ish now with delayed extraction. -gg 3/15/2001 */
    if (PLR_FLAGGED(victim, PLR_NOTDEADYET) || MOB_FLAGGED(victim, MOB_NOTDEADYET))
      return (-1);

    log("SYSERR: Attempt to damage corpse '%s' in room #%d by '%s'.",
		GET_NAME(victim), GET_ROOM_VNUM(IN_ROOM(victim)), GET_NAME(ch));
    die(victim);
    return (-1);			/* -je, 7/7/92 */
  }

  /* peaceful rooms */
  if (ch != victim && ROOM_FLAGGED(IN_ROOM(ch), ROOM_PEACEFUL)) {
    send_to_char(ch, "This room just has such a peaceful, easy feeling...\r\n");
    return (0);
  }

  /* shopkeeper protection */
  if (!ok_damage_shopkeeper(ch, victim))
    return (0);

  /* You can't damage an immortal! */
  if (!IS_NPC(victim) && (GET_LEVEL(victim) >= LVL_IMMORT))
    dam = 0;

  if (victim != ch) {
    /* Start the attacker fighting the victim */
    if (GET_POS(ch) > POS_STUNNED && (FIGHTING(ch) == NULL))
      set_fighting(ch, victim);

    /* Start the victim fighting the attacker */
    if (GET_POS(victim) > POS_STUNNED && (FIGHTING(victim) == NULL)) {
      set_fighting(victim, ch);
      if (MOB_FLAGGED(victim, MOB_MEMORY) && !IS_NPC(ch))
	remember(victim, ch);
    }
  }

  /* If you attack a pet, it hates your guts */
  if (victim->master == ch)
    stop_follower(victim);

  /* If the attacker is invisible, he becomes visible */
  if (AFF_FLAGGED(ch, AFF_INVISIBLE | AFF_HIDE))
    appear(ch);

  /* Cut damage in half if victim has sanct, to a minimum 1 */
  if (AFF_FLAGGED(victim, AFF_SANCTUARY) && dam >= 2)
    dam /= 2;

  /* Check for PK if this is not a PK MUD */
  if (!pk_allowed) {
    check_killer(ch, victim);
    if (PLR_FLAGGED(ch, PLR_KILLER) && (ch != victim))
      dam = 0;
  }

  /* Set the maximum damage per round and subtract the hit points */
  dam = MAX(MIN(dam, 100), 0);
  GET_HIT(victim) -= dam;

  /* Gain exp for the hit */
  if (ch != victim)
    gain_exp(ch, GET_LEVEL(victim) * dam);

  update_pos(victim);

  /*
   * skill_message sends a message from the messages file in lib/misc.
   * dam_message just sends a generic "You hit $n extremely hard.".
   * skill_message is preferable to dam_message because it is more
   * descriptive.
   * 
   * If we are _not_ attacking with a weapon (i.e. a spell), always use
   * skill_message. If we are attacking with a weapon: If this is a miss or a
   * death blow, send a skill_message if one exists; if not, default to a
   * dam_message. Otherwise, always send a dam_message.
   */
  if (!IS_WEAPON(attacktype))
    skill_message(dam, ch, victim, attacktype);
  else {
    if (GET_POS(victim) == POS_DEAD || dam == 0) {
      if (!skill_message(dam, ch, victim, attacktype))
	dam_message(dam, ch, victim, attacktype);
    } else {
      dam_message(dam, ch, victim, attacktype);
    }
  }

  /* Use send_to_char -- act() doesn't send message if you are DEAD. */
  switch (GET_POS(victim)) {
  case POS_MORTALLYW:
    act("$n is mortally wounded, and will die soon, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are mortally wounded, and will die soon, if not aided.\r\n");
    break;
  case POS_INCAP:
    act("$n is incapacitated and will slowly die, if not aided.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are incapacitated an will slowly die, if not aided.\r\n");
    break;
  case POS_STUNNED:
    act("$n is stunned, but will probably regain consciousness again.", TRUE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You're stunned, but will probably regain consciousness again.\r\n");
    break;
  case POS_DEAD:
    act("$n is dead!  R.I.P.", FALSE, victim, 0, 0, CommTarget::TO_ROOM);
    send_to_char(victim, "You are dead!  Sorry...\r\n");
    break;

  default:			/* >= POSITION SLEEPING */
    if (dam > (GET_MAX_HIT(victim) / 4))
      send_to_char(victim, "That really did HURT!\r\n");

    if (GET_HIT(victim) < (GET_MAX_HIT(victim) / 4)) {
      send_to_char(victim, "%sYou wish that your wounds would stop BLEEDING so much!%s\r\n",
		CCRED(victim, C_SPR), CCNRM(victim, C_SPR));
      if (ch != victim && MOB_FLAGGED(victim, MOB_WIMPY))
	do_flee(victim, NULL, 0, 0);
    }
    if (!IS_NPC(victim) && GET_WIMP_LEV(victim) && (victim != ch) &&
	GET_HIT(victim) < GET_WIMP_LEV(victim) && GET_HIT(victim) > 0) {
      send_to_char(victim, "You wimp out, and attempt to flee!\r\n");
      do_flee(victim, NULL, 0, 0);
    }
    break;
  }

  /* Help out poor linkless people who are attacked */
  if (!IS_NPC(victim) && !(victim->desc) && GET_POS(victim) > POS_STUNNED) {
    do_flee(victim, NULL, 0, 0);
    if (!FIGHTING(victim)) {
      act("$n is rescued by divine forces.", FALSE, victim, 0, 0, CommTarget::TO_ROOM);
      GET_WAS_IN(victim) = IN_ROOM(victim);
      char_from_room(victim);
      char_to_room(victim, 0);
    }
  }

  /* stop someone from fighting if they're stunned or worse */
  if (GET_POS(victim) <= POS_STUNNED && FIGHTING(victim) != NULL)
    stop_fighting(victim);

  /* Uh oh.  Victim died. */
  if (GET_POS(victim) == POS_DEAD) {
    if (ch != victim && (IS_NPC(victim) || victim->desc)) {
      if (AFF_FLAGGED(ch, AFF_GROUP))
	group_gain(ch, victim);
      else
        solo_gain(ch, victim);
    }

    if (!IS_NPC(victim)) {
      mudlog(BRF, LVL_IMMORT, TRUE, "%s killed by %s at %s", GET_NAME(victim), GET_NAME(ch), world[IN_ROOM(victim)].name);
      if (MOB_FLAGGED(ch, MOB_MEMORY))
	forget(ch, victim);
    }
    die(victim);
    return (-1);
  }
  return (dam);
}
Beispiel #2
0
static void MVD_Stats_Gather_AlivePlayer(int player_index)
{
	int x; // item index
	int z; // item index
	int i = player_index;
	int killdiff;
	int taken = 0;
	int ammotaken[AMMO_TYPES] = {0, 0, 0, 0};
	qbool had_mega;
	qbool has_mega;

	for (x=GA_INFO;x<=RA_INFO && mvd_cg_info.deathmatch!=4;x++){
		if(mvd_new_info[i].p_info->stats[STAT_ITEMS] & mvd_wp_info[x].it) {

			if (!mvd_new_info[i].mvdinfo.itemstats[x].has) {
				taken |= (1 << x);
				MVD_Set_Armor_Stats(x,i);
				mvd_new_info[i].mvdinfo.itemstats[x].count++;
				mvd_new_info[i].mvdinfo.itemstats[x].lost=mvd_new_info[i].p_info->stats[STAT_ARMOR];
				mvd_new_info[i].mvdinfo.itemstats[x].has=1;
				mvd_new_info[i].mvdinfo.itemstats[x].starttime = cls.demotime;
			}

			if (mvd_new_info[i].mvdinfo.itemstats[x].lost < mvd_new_info[i].p_info->stats[STAT_ARMOR]) {
				taken |= (1 << x);
				mvd_new_info[i].mvdinfo.itemstats[x].count++;
				mvd_new_info[i].mvdinfo.itemstats[x].starttime = cls.demotime;
			}
			mvd_new_info[i].mvdinfo.itemstats[x].lost=mvd_new_info[i].p_info->stats[STAT_ARMOR];
		}
	}

	for (x=RING_INFO;x<=PENT_INFO && mvd_cg_info.deathmatch!=4;x++){
		if(!mvd_new_info[i].mvdinfo.itemstats[x].has && mvd_new_info[i].p_info->stats[STAT_ITEMS] & mvd_wp_info[x].it){
			taken |= (1 << x);
			mvd_new_info[i].mvdinfo.itemstats[x].has = 1;
			if (x==PENT_INFO && (powerup_cam_active == 3 || powerup_cam_active == 2)){
				pent_mentioned=0;
				pent_is_active=1;
				powerup_cam_active-=2;
			}
			if (x==QUAD_INFO && (powerup_cam_active == 3 || powerup_cam_active == 1)){
				quad_mentioned=0;
				quad_is_active=1;
				powerup_cam_active-=1;
			}
			mvd_new_info[i].mvdinfo.itemstats[x].starttime = cls.demotime;
			mvd_new_info[i].mvdinfo.itemstats[x].count++;
		}
		if (mvd_new_info[i].mvdinfo.itemstats[x].has && !(mvd_new_info[i].p_info->stats[STAT_ITEMS] & mvd_wp_info[x].it)){
			mvd_new_info[i].mvdinfo.itemstats[x].has = 0;
			if (x==QUAD_INFO && quad_is_active){
				quad_is_active=0;
			}
			if (x==PENT_INFO && pent_is_active){
				pent_is_active=0;
			}
			mvd_new_info[i].mvdinfo.itemstats[x].runs[mvd_new_info[i].mvdinfo.itemstats[x].run].starttime = mvd_new_info[i].mvdinfo.itemstats[x].starttime;
			mvd_new_info[i].mvdinfo.itemstats[x].runs[mvd_new_info[i].mvdinfo.itemstats[x].run].time = cls.demotime - mvd_new_info[i].mvdinfo.itemstats[x].starttime;
			mvd_new_info[i].mvdinfo.itemstats[x].run++;
		}
	}

	had_mega = mvd_new_info[i].mvdinfo.itemstats[MH_INFO].has > 0;
	has_mega = mvd_new_info[i].p_info->stats[STAT_ITEMS] & IT_SUPERHEALTH;
	if (!had_mega && has_mega) {
		// Picked up mega
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].mention = 1;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].has = 1;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].count++;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].starttime = cls.demotime;
	}
	else if (has_mega && mvd_new_info[i].mvdinfo.itemstats[MH_INFO].lost < mvd_new_info[i].p_info->stats[STAT_HEALTH] && mvd_new_info[i].p_info->stats[STAT_HEALTH] > 100) {
		// They already had mega health but health increased - must have been another mega
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].mention = 1;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].has++;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].count++;
		mvd_new_info[i].mvdinfo.itemstats[MH_INFO].starttime = cls.demotime;
	}
	mvd_new_info[i].mvdinfo.itemstats[MH_INFO].lost = mvd_new_info[i].p_info->stats[STAT_HEALTH];

	if (had_mega && !has_mega) {
		// Might have had two megas ticking down, create as many clocks as necessary
		while (mvd_new_info[i].mvdinfo.itemstats[MH_INFO].has--) {
			MVD_ClockStart(MH_INFO);
		}
	}

	for (z=RING_INFO;z<=PENT_INFO;z++){
		if (mvd_new_info[i].mvdinfo.itemstats[z].has == 1){
			mvd_new_info[i].mvdinfo.itemstats[z].runs[mvd_new_info[i].mvdinfo.itemstats[z].run].starttime = mvd_new_info[i].mvdinfo.itemstats[z].starttime;
			mvd_new_info[i].mvdinfo.itemstats[z].runs[mvd_new_info[i].mvdinfo.itemstats[z].run].time = cls.demotime - mvd_new_info[i].mvdinfo.itemstats[z].starttime;
		}
	}

	if (mvd_new_info[i].mvdinfo.lastfrags != mvd_new_info[i].p_info->frags ){
		if (mvd_new_info[i].mvdinfo.lastfrags < mvd_new_info[i].p_info->frags){
			killdiff = mvd_new_info[i].p_info->frags - mvd_new_info[i].mvdinfo.lastfrags;
			for (z=0;z<8;z++){
				if (z == MVD_Weapon_LWF(mvd_new_info[i].mvdinfo.lfw))
					mvd_new_info[i].mvdinfo.killstats.normal[z].kills+=killdiff;
			}
			if (mvd_new_info[i].mvdinfo.lfw == -1)
				mvd_new_info[i].mvdinfo.spawntelefrags+=killdiff;
			for(z=8;z<11;z++){
				if(mvd_new_info[i].mvdinfo.itemstats[z].has)
					mvd_new_info[i].mvdinfo.itemstats[z].runs[mvd_new_info[i].mvdinfo.itemstats[z].run].frags+=killdiff;
			}
			mvd_new_info[i].mvdinfo.runs[mvd_new_info[i].mvdinfo.run].frags++;
		}else if (mvd_new_info[i].mvdinfo.lastfrags > mvd_new_info[i].p_info->frags){
			killdiff = mvd_new_info[i].mvdinfo.lastfrags - mvd_new_info[i].p_info->frags ;
			for (z=AXE_INFO;z<=LG_INFO;z++){
				if (z == MVD_Weapon_LWF(mvd_new_info[i].mvdinfo.lfw))
					mvd_new_info[i].mvdinfo.killstats.normal[z].teamkills+=killdiff;
			}
			if (mvd_new_info[i].mvdinfo.lfw == -1){
				mvd_new_info[i].mvdinfo.teamspawntelefrags+=killdiff;

			}
			for(z=8;z<11;z++){
				if(mvd_new_info[i].mvdinfo.itemstats[z].has)
					mvd_new_info[i].mvdinfo.itemstats[z].runs[mvd_new_info[i].mvdinfo.itemstats[z].run].teamfrags+=killdiff;
			}
			mvd_new_info[i].mvdinfo.runs[mvd_new_info[i].mvdinfo.run].teamfrags++;
		}


		mvd_new_info[i].mvdinfo.lastfrags = mvd_new_info[i].p_info->frags ;
	}

	mvd_new_info[i].mvdinfo.runs[mvd_new_info[i].mvdinfo.run].time=cls.demotime - mvd_new_info[i].mvdinfo.das.alivetimestart;

	if (mvd_new_info[i].mvdinfo.lfw == -1){
		if (mvd_new_info[i].mvdinfo.lastfrags > mvd_new_info[i].p_info->frags ){
			mvd_new_info[i].mvdinfo.teamspawntelefrags += mvd_new_info[i].p_info->frags - mvd_new_info[i].mvdinfo.lastfrags ;
		}else if (mvd_new_info[i].mvdinfo.lastfrags < mvd_new_info[i].p_info->frags ){
			mvd_new_info[i].mvdinfo.spawntelefrags += mvd_new_info[i].p_info->frags -mvd_new_info[i].mvdinfo.lastfrags  ;
		}
		mvd_new_info[i].mvdinfo.lastfrags = mvd_new_info[i].p_info->frags;
	}

	if (mvd_new_info[i].p_state->weaponframe > 0)
		mvd_new_info[i].mvdinfo.lfw=mvd_new_info[i].p_info->stats[STAT_ACTIVEWEAPON];
	if (mvd_cg_info.deathmatch!=4){
		MVD_Status_WP(i, &taken);
		for (z=SSG_INFO;z<=RA_INFO;z++) {
			MVD_Status_Announcer(i,z);
		}
	}

	for (x = 0; x < AMMO_TYPES; x++) {
		int ammo_new = mvd_new_info[i].p_info->stats[STAT_SHELLS + x];
		int ammo_old = mvd_new_info[i].mvdinfo.ammostats[x];
		if (mvd_new_info[i].mvdinfo.initialized && ammo_new > ammo_old) {
			int diff = ammo_new - ammo_old;
			ammotaken[x] = diff;
		}
		mvd_new_info[i].mvdinfo.ammostats[x] =
			mvd_new_info[i].p_info->stats[STAT_SHELLS + x];
	}

	for (x = 0; x < mvd_info_types; x++) {
		if (taken & (1 << x)) {
			qbool weapon_from_backpack =
				IS_WEAPON(x) && MVD_Weapon_From_Backpack(x, taken, ammotaken);
			// don't start clock if item was from backpack
			qbool add_clock = !weapon_from_backpack;
			Com_DPrintf("player %i took %i, weapon from backpack: %s\n",
					i, x, weapon_from_backpack ? "yes" : "no");

			MVD_Took(i, x, add_clock);
		}
	}
}