Beispiel #1
0
/* this function takes a real number for a room and returns:
   FALSE - mortals shouldn't be able to teleport to this destination 
   TRUE - mortals CAN teleport to this destination 
 * accepts NULL ch data
 */
int valid_mortal_tele_dest(struct char_data *ch, room_rnum dest, bool dim_lock) {

  if (dest == NOWHERE)
    return FALSE;

  if (IS_AFFECTED(ch, AFF_DIM_LOCK) && dim_lock)
    return FALSE;
  
  /* this function needs a vnum, not rnum */
  if (ch && !House_can_enter(ch, GET_ROOM_VNUM(dest)))
    return FALSE;

  if (ZONE_FLAGGED(GET_ROOM_ZONE(dest), ZONE_NOASTRAL))
    return FALSE;

  if (ROOM_FLAGGED(dest, ROOM_PRIVATE))
    return FALSE;

  if (ROOM_FLAGGED(dest, ROOM_DEATH))
    return FALSE;

  if (ROOM_FLAGGED(dest, ROOM_GODROOM))
    return FALSE;

  if (ZONE_FLAGGED(GET_ROOM_ZONE(dest), ZONE_CLOSED))
    return FALSE;

  if (ZONE_FLAGGED(GET_ROOM_ZONE(dest), ZONE_NOASTRAL))
    return FALSE;

  //passed all tests!
  return TRUE;
}
/* attaches room vnum to msg and sends it to script_log */
void wld_log(room_data *room, const char *format, ...) {
	va_list args;
	char output[MAX_STRING_LENGTH];

	snprintf(output, sizeof(output), "Room %d :: %s", GET_ROOM_VNUM(room), format);

	va_start(args, format);
	script_vlog(output, args);
	va_end(args);
}
Beispiel #3
0
int Board_display_msg(int board_type, struct char_data *ch, char *arg, struct obj_data *board)
{
  char number[MAX_INPUT_LENGTH], buffer[MAX_STRING_LENGTH];
  int msg, ind;

  one_argument(arg, number);
  if (!*number)
    return (0);
  if (isname(number, board->name))	/* so "read board" works */
    return (Board_show_board(board_type, ch, arg, board));
  if (!is_number(number))	/* read 2.mail, look 2.sword */
    return (0);
  if (!(msg = atoi(number)))
    return (0);

  if (GET_LEVEL(ch) < READ_LVL(board_type)) {
    send_to_char(ch, "You try but fail to understand the holy words.\r\n");
    return (1);
  }
  if (!num_of_msgs[board_type]) {
    send_to_char(ch, "The board is empty!\r\n");
    return (1);
  }
  if (msg < 1 || msg > num_of_msgs[board_type]) {
    send_to_char(ch, "That message exists only in your imagination.\r\n");
    return (1);
  }
#if NEWEST_AT_TOP
  ind = num_of_msgs[board_type] - msg;
#else
  ind = msg - 1;
#endif
  if (MSG_SLOTNUM(board_type, ind) < 0 ||
      MSG_SLOTNUM(board_type, ind) >= INDEX_SIZE) {
    send_to_char(ch, "Sorry, the board is not working.\r\n");
    log("SYSERR: Board is screwed up. (Room #%d)", GET_ROOM_VNUM(IN_ROOM(ch)));
    return (1);
  }
  if (!(MSG_HEADING(board_type, ind))) {
    send_to_char(ch, "That message appears to be screwed up.\r\n");
    return (1);
  }
  if (!(msg_storage[MSG_SLOTNUM(board_type, ind)])) {
    send_to_char(ch, "That message seems to be empty.\r\n");
    return (1);
  }
  snprintf(buffer, sizeof(buffer), "Message %d : %s\r\n\r\n%s\r\n", msg,
	  MSG_HEADING(board_type, ind),
	  msg_storage[MSG_SLOTNUM(board_type, ind)]);

  page_string(ch->desc, buffer, TRUE);

  return (1);
}
Beispiel #4
0
void do_mlist (struct char_data *ch, char *input)
{
	if (!(*input))
		list_mob_zone(ch,(-1)); 
	else {
		skip_spaces(&input);
		if (is_number(input))
			list_mob_zone(ch,atoi(input));
		else
			list_mob_zone(ch,((GET_ROOM_VNUM(IN_ROOM(ch))) /100)); 
	}
	return; 
}
Beispiel #5
0
void underwater_check(void)
{
	DESCRIPTOR_DATA *d;
	for (d = descriptor_list; d; d = d->next)
	{
		if (d->character
			&& SECT(d->character->in_room) == SECT_UNDERWATER
			&& !IS_GOD(d->character)
			&& !AFF_FLAGGED(d->character, AFF_WATERBREATH))
		{
			sprintf(buf, "Player %s died under water (room %d)",
				GET_NAME(d->character), GET_ROOM_VNUM(d->character->in_room));

			Damage dmg(SimpleDmg(TYPE_WATERDEATH), MAX(1, GET_REAL_MAX_HIT(d->character) >> 2), FightSystem::UNDEF_DMG);
			dmg.flags.set(FightSystem::NO_FLEE);

			if (dmg.process(d->character, d->character) < 0)
			{
				log("%s",buf);
			}
		}
	}
Beispiel #6
0
int Board_remove_msg(int board_type, struct char_data *ch, char *arg, struct obj_data *board)
{
  (void)board;
  int ind, msg, slot_num;
  char number[MAX_INPUT_LENGTH], buf[MAX_INPUT_LENGTH];
  struct descriptor_data *d;

  one_argument(arg, number);

  if (!*number || !is_number(number))
    return (0);
  if (!(msg = atoi(number)))
    return (0);

  if (!num_of_msgs[board_type]) {
    send_to_char(ch, "The board is empty!\r\n");
    return (1);
  }
  if (msg < 1 || msg > num_of_msgs[board_type]) {
    send_to_char(ch, "That message exists only in your imagination.\r\n");
    return (1);
  }
#if NEWEST_AT_TOP
  ind = num_of_msgs[board_type] - msg;
#else
  ind = msg - 1;
#endif
  if (!MSG_HEADING(board_type, ind)) {
    send_to_char(ch, "That message appears to be screwed up.\r\n");
    return (1);
  }
  snprintf(buf, sizeof(buf), "(%s)", GET_NAME(ch));
  if (GET_LEVEL(ch) < REMOVE_LVL(board_type) &&
      !(strstr(MSG_HEADING(board_type, ind), buf))) {
    send_to_char(ch, "You are not holy enough to remove other people's messages.\r\n");
    return (1);
  }
  if (GET_LEVEL(ch) < MSG_LEVEL(board_type, ind)) {
    send_to_char(ch, "You can't remove a message holier than yourself.\r\n");
    return (1);
  }
  slot_num = MSG_SLOTNUM(board_type, ind);
  if (slot_num < 0 || slot_num >= INDEX_SIZE) {
    send_to_char(ch, "That message is majorly screwed up.\r\n");
    log("SYSERR: The board is seriously screwed up. (Room #%d)", GET_ROOM_VNUM(IN_ROOM(ch)));
    return (1);
  }
  for (d = descriptor_list; d; d = d->next)
    if (STATE(d) == CON_PLAYING && d->str == &(msg_storage[slot_num])) {
      send_to_char(ch, "At least wait until the author is finished before removing it!\r\n");
      return (1);
    }
  if (msg_storage[slot_num])
    free(msg_storage[slot_num]);
  msg_storage[slot_num] = 0;
  msg_storage_taken[slot_num] = 0;
  if (MSG_HEADING(board_type, ind))
    free(MSG_HEADING(board_type, ind));

  for (; ind < num_of_msgs[board_type] - 1; ind++) {
    MSG_HEADING(board_type, ind) = MSG_HEADING(board_type, ind + 1);
    MSG_SLOTNUM(board_type, ind) = MSG_SLOTNUM(board_type, ind + 1);
    MSG_LEVEL(board_type, ind) = MSG_LEVEL(board_type, ind + 1);
  }
  MSG_HEADING(board_type, num_of_msgs[board_type] - 1) = NULL;
  MSG_SLOTNUM(board_type, num_of_msgs[board_type] - 1) = 0;
  MSG_LEVEL(board_type, num_of_msgs[board_type] - 1) = 0;
  num_of_msgs[board_type]--;

  send_to_char(ch, "Message removed.\r\n");
  snprintf(buf, sizeof(buf), "$n just removed message %d.", msg);
  act(buf, FALSE, ch, 0, 0, CommTarget::TO_ROOM);
  Board_save_board(board_type);

  return (1);
}
Beispiel #7
0
void list_mob_zone (struct char_data *ch, int whichzone)
{

	int i=0;
	int j=0;
	mob_vnum first_z_mob=0; /*vnum of first mob in zone list*/
	mob_vnum last_z_mob=0; /*vnum of last mob in zone list */
	int char_zone = ((GET_ROOM_VNUM(IN_ROOM(ch)))/100); /*initialize to current zone    */
	char *mbuf = get_buffer(MAX_STRING_LENGTH);

	mbuf[0]='\0'; 
	if (whichzone > (-1))
		char_zone = whichzone; /*see if specific zone was passed as arg*/

	while (j!= char_zone) {
		first_z_mob++;
		j=(GET_MOB_VNUM(&mob_proto[i])/100);
		i++;

		/*
		 * some zones have 100+ rooms but not 100+ items/mobs.
		 * To find the needed mobs/objects, 
		 * search backwards for previous zone w/them.
		 */
		if (j>char_zone) {
			if (char_zone>0) {
				char_zone--;
				first_z_mob=0;
				i=0;
				j=0; 
			} else {
				extended_mudlog(NRM, SYSL_BUGS, TRUE, "mlist looked for a zone < 0");
				release_buffer(mbuf);
				return;
			}
		}
	}

	first_z_mob --;
	last_z_mob=first_z_mob;


	while (j == char_zone) {
		j=(GET_MOB_VNUM(&mob_proto[i])/100);
		last_z_mob++;
		i++; 
	}

	if (first_z_mob<0)
		first_z_mob ++;
	for (i=first_z_mob;i<last_z_mob;i++) {
		sprintf(mbuf+strlen(mbuf),"[%5d] %-30s  (difficulty %d)\r\n",
		GET_MOB_VNUM(&mob_proto[i]),
		mob_proto[i].player.short_descr,
		mob_proto[i].mob_specials.difficulty); 
	}
	if (strlen(mbuf)<5)
		send_to_char ("There are no mobs in the zone you requested.\r\n",ch);
	else
		page_string (ch->desc,mbuf,1);

	release_buffer(mbuf);
	return;
}
Beispiel #8
0
void list_object_zone (struct char_data *ch, int whichzone)
{
	int i=0;
	int j=0;
	obj_vnum first_z_obj=0; /*vnum of first obj in zone list*/
	obj_vnum last_z_obj=0; /*vnum of last obj in zone list */
	int char_zone = ((GET_ROOM_VNUM(IN_ROOM(ch)))/100); /*initialize to current zone    */
	char *obuf = get_buffer(MAX_STRING_LENGTH);

	obuf[0]='\0'; 
	if (whichzone > (-1)) char_zone = whichzone; /*see if specific zone was passed as arg*/

	while (j!= char_zone) {
		first_z_obj++;
		j=(GET_OBJ_VNUM(&obj_proto[i])/100);
		i++;

		/*
		 * some zones have 100+ rooms but not 100+ items/objs.
		 * To find the needed objs/objects, 
		 * search backwards for previous zones w/them.
		 */
		if (j>char_zone) {
			if (char_zone>0) {
				char_zone--;
				first_z_obj=0;
				i=0;
				j=0; 
			} else {
				extended_mudlog(NRM, SYSL_BUGS, TRUE, "olist looked for a zone < 0");
				release_buffer(obuf);
				return;
			}
		}
	}

	first_z_obj --;
	last_z_obj=first_z_obj;

	while (j == char_zone) {
		j=(GET_OBJ_VNUM(&obj_proto[i])/100);
		last_z_obj++;
		i++; 
	}

	if (first_z_obj<0)
		first_z_obj ++;
	for (i=first_z_obj;i<last_z_obj;i++) {
		sprintf(obuf+strlen(obuf),"[%5d] %-32s",
		GET_OBJ_VNUM(&obj_proto[i]),
		obj_proto[i].short_description);

		j=obj_proto[i].obj_flags.type_flag;
		sprintf(obuf+strlen(obuf)," %s ", item_types[(int)obj_proto[i].obj_flags.type_flag]);
		if ((j == ITEM_WORN) || (j== ITEM_ARMOR)) {
			sprintf(obuf+strlen(obuf)," (-%d AC 1) ",GET_OBJ_VAL(&obj_proto[i],0));
			j=get_armor_ac (&obj_proto[i]);
			if (j!=0)
				sprintf(obuf + strlen(obuf), "(-%d AC 2)",j); 
		}

		if (j==ITEM_WEAPON) {
			sprintf(obuf+strlen(obuf),"(Ave dam: %.1f) ", 
			(((GET_OBJ_VAL(&obj_proto[i], 2) + 1) /2.0) * GET_OBJ_VAL(&obj_proto[i], 1))); 
			j = get_weapon_dam(&obj_proto[i]);
			if (j!=0) sprintf(buf+strlen(buf), " +%d DAM ",j); 
		}
		sprintbit(GET_OBJ_WEAR(&obj_proto[i]), wear_bits, obuf+strlen(obuf), sizeof(obuf));
		sprintf(obuf+strlen(obuf),"\r\n");
	}
	if (strlen(obuf)<5) send_to_char ("There are no objects in the zone you requested.\r\n",ch);
	else page_string (ch->desc,obuf,1);
	release_buffer(obuf);
	return;
}
Beispiel #9
0
void list_room_zone (struct char_data *ch, int whichzone)
{
	int i=0;
	int j=0;
	room_vnum first_z_room=0; /*vnum of first obj in zone list*/
	room_vnum last_z_room=0; /*vnum of last obj in zone list */
	int char_zone = ((GET_ROOM_VNUM(IN_ROOM(ch)))/100); /*initialize to current zone    */
	char *rbuf = get_buffer(MAX_STRING_LENGTH);

	rbuf[0]='\0'; 
	if (whichzone > (-1))
		char_zone = whichzone; /*see if specific zone was passed as arg*/

	while (j!= char_zone) {
		first_z_room++;
		j=(world[i].number/100);
		i++;

		/*
		 * some zones have 100+ rooms but not 100+ items/objs.
		 * To find the needed objs/objects,
		 * search backwards for previous zone.
		 */
		if (j>char_zone) {
			if (char_zone>0) {
				char_zone--;
				first_z_room=0;
				i=0;
				j=0; 
			} else {
				extended_mudlog(NRM, SYSL_BUGS, TRUE, "rlist looked for a zone < 0");
				release_buffer(rbuf);
				return;
			}
		}
	}

	first_z_room --;
	last_z_room=first_z_room;


	while (j == char_zone) {
		j=(world[i].number/100);
		last_z_room++;
		i++; 
	}

	if (first_z_room<0)
		first_z_room ++;
	for (i=first_z_room;i<last_z_room;i++) {
		sprintf(rbuf+strlen(rbuf),"[%5d]  %s\r\n",
		world[i].number,
		world[i].name);
	}
	
	if (strlen(rbuf)<5)
		send_to_char ("There are no rooms in the zone you requested.\r\n",ch);
	else
		page_string (ch->desc, rbuf, 1);

	release_buffer(rbuf);
	return;
}
Beispiel #10
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 #11
0
/* do_simple_move assumes
 *    1. That there is no master and no followers.
 *    2. That the direction exists.
 *
 *   Returns :
 *   1 : If succes.
 *   0 : If fail
 */
int do_simple_move(struct char_data *ch, int dir, int need_specials_check)
{
  char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */
  room_rnum was_in;

  int need_movement, moveadd = 0;
  struct obj_data *k;

  /*
   * Check for special routines (North is 1 in command list, but 0 here) Note
   * -- only check if following; this avoids 'double spec-proc' bug
   */
  if (need_specials_check && special(ch, dir + 1, throwaway))
    return (0);

  /* blocked by a leave trigger ? */
  if (!leave_mtrigger(ch, dir))
    return 0;
  if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir))
    return 0;

  /* charmed? */
  if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) {
    send_to_char(ch, "The thought of leaving your master makes you weep.\r\n");
    act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
    return (0);
  }

  /* if this room or the one we're going to needs a boat, check for one */
  if ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) ||
      (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) {
    if (!has_boat(ch)) {
      send_to_char(ch, "You need a boat to go there.\r\n");
      return (0);
    }
  }

  /* move points needed is avg. move loss for src and destination sect type
   * You know .. I don't like this system, let's base this not ONLY on terrain type
   * but also on dex of char. 
   * Needs to adjust on max abils
   * Original:
   * need_movement = (movement_loss[SECT(IN_ROOM(ch))] +
		   movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2;
   */

   if (GET_DEX(ch) <= 5) 				/* 0(1?)-5 Dex */
      moveadd = 8;
   if ((GET_DEX(ch) >= 6) && (GET_DEX(ch) <= 10)) 	/* 6-10 Dex */
      moveadd = 6;
   if ((GET_DEX(ch) >= 11) && (GET_DEX(ch) <= 15))  	/* 11-15 Dex */
      moveadd = 4;
   if (GET_DEX(ch) >= 16) 				/* 16+ Up to ..? Dex */
      moveadd = 2;

   need_movement = (movement_loss[SECT(IN_ROOM(ch))] + movement_loss[SECT(EXIT(ch, dir)->to_room)] + moveadd) / 2;

  if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
    if (need_specials_check && ch->master)
      send_to_char(ch, "You are too exhausted to follow.\r\n");
    else
      send_to_char(ch, "You are too exhausted.\r\n");

    return (0);
  }
  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) {
    if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) {
      send_to_char(ch, "That's private property -- no trespassing!\r\n");
      return (0);
    }
  }
  if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) &&
     num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= tunnel_size) {
    if (tunnel_size > 1)
      send_to_char(ch, "There isn't enough room for you to go there!\r\n");
    else
      send_to_char(ch, "There isn't enough room there for more than one person!\r\n");
    return (0);
  }


 /* Room big enough for you? */
   if ((SIZE(EXIT(ch, dir)->to_room) < GET_SIZE(ch)) && (SIZE(EXIT(ch, dir)->to_room) != SIZE_SPECIAL) && (GET_LEVEL(ch) < LVL_GOD)) { //GOD+ can enter any room
    send_to_char(ch, "You are too big to fit in there!\r\n");
    return (0);
  }


  /* Mortals and low level gods cannot enter greater god rooms. */
/* irrelevant because of min/max level -mak 8.21.05 -reinstated 2.9.06 

  if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) &&
	GET_LEVEL(ch) < LVL_GOD) { 
    send_to_char(ch, "You aren't godly enough to use that room!\r\n");
    return (0);
  }
uncomment to fix GODROOM */

/* No access for non-IMPs */
  if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_IMPROOM) &&
	GET_LEVEL(ch) < LVL_IMPL) {
    send_to_char(ch, "You dare not disturb the Implementors!\r\n");
    return (0);
  }
  if (GET_LEVEL(ch) < ROOM_MIN_LEVEL(EXIT(ch, dir)->to_room)) {
    if (world[EXIT(ch, dir)->to_room].max_level_message ) {
       send_to_char(ch, world[EXIT(ch, dir)->to_room].min_level_message);
       send_to_char(ch, "\r\n");
    }
    else
    send_to_char(ch, "You are not experienced enough to enter that room.\r\n");
    return 0;
  }
  if (ROOM_MAX_LEVEL(EXIT(ch, dir)->to_room) > 0) {
   if (GET_LEVEL(ch) > ROOM_MAX_LEVEL(EXIT(ch, dir)->to_room)  && GET_LEVEL(ch) < LVL_SAINT ) {
    if (world[EXIT(ch, dir)->to_room].max_level_message ){
       send_to_char(ch, world[EXIT(ch, dir)->to_room].max_level_message);
       send_to_char(ch, "\r\n");
    }
    else
    send_to_char(ch, "You are too experienced to enter that room.\r\n");
    return 0;
   }
  }
  if (AFF_FLAGGED(ch, AFF_FLEET_FEET)) {
      need_movement = need_movement / 2;
      if (need_movement < 2) need_movement = 1;}

  if (AFF_FLAGGED(ch, AFF_AIRWALK)) need_movement = 1;
  
  /* Now we know we're allowed to go into the room. */
  if (GET_LEVEL(ch) < LVL_SAINT && !IS_NPC(ch))
    GET_MOVE(ch) -= need_movement;

  if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
    char buf2[MAX_STRING_LENGTH];

    snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]);
    act(buf2, TRUE, ch, 0, 0, TO_ROOM);
  }
  was_in = IN_ROOM(ch);
  char_from_room(ch);
  char_to_room(ch, world[was_in].dir_option[dir]->to_room);

  /* move them first, then move them back if they aren't allowed to go. */
  /* see if an entry trigger disallows the move */
  if (!entry_mtrigger(ch) || !enter_wtrigger(&world[IN_ROOM(ch)], ch, dir)) {
    char_from_room(ch);
    char_to_room(ch, was_in);
    return 0;
  }

  if (!AFF_FLAGGED(ch, AFF_SNEAK))
    act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);

  if (ch->desc != NULL)
    look_at_room(IN_ROOM(ch), ch, 0);

  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_SAINT) {
    clanlog(ch, "%s entered a Death Room", GET_NAME(ch));
    was_in = IN_ROOM(ch);
    log_death_trap(ch);
    death_cry(ch);
    /* Fix the PCs size first if it needs fixing */
    fix_size(ch);

    extract_char(ch);

    for (k = world[was_in].contents; k; k = world[was_in].contents)
        extract_obj(k);

    return (0);
  }

  entry_memory_mtrigger(ch);
  if (!greet_mtrigger(ch, dir)) {
    char_from_room(ch);
    char_to_room(ch, was_in);
    look_at_room(IN_ROOM(ch), ch, 0);
  } else greet_memory_mtrigger(ch);

  /* send warning message if moves are getting low */
  if ( GET_MOVE(ch) < (GET_MAX_MOVE(ch) / 10) )
  {
    send_to_char(ch, "You cannot go much further.\r\n");
  }

  return (1);
}
Beispiel #12
0
/** Move a PC/NPC character from their current location to a new location. This
 * is the standard movement locomotion function that all normal walking
 * movement by characters should be sent through. This function also defines
 * the move cost of normal locomotion as:
 * ( (move cost for source room) + (move cost for destination) ) / 2
 *
 * @pre Function assumes that ch has no master controlling character, that
 * ch has no followers (in other words followers won't be moved by this
 * function) and that the direction traveled in is one of the valid, enumerated
 * direction.
 * @param ch The character structure to attempt to move.
 * @param dir The defined direction (NORTH, SOUTH, etc...) to attempt to
 * move into.
 * @param need_specials_check If TRUE will cause
 * @retval int 1 for a successful move (ch is now in a new location)
 * or 0 for a failed move (ch is still in the original location). */
int do_simple_move(struct char_data *ch, int dir, int need_specials_check)
{
  /* Begin Local variable definitions */
  /*---------------------------------------------------------------------*/
  /* Used in our special proc check. By default, we pass a NULL argument
   * when checking for specials */
  char spec_proc_args[MAX_INPUT_LENGTH] = "";
  /* The room the character is currently in and will move from... */
  room_rnum was_in = IN_ROOM(ch);
  /* ... and the room the character will move into. */
  room_rnum going_to = EXIT(ch, dir)->to_room;
  /* How many movement points are required to travel from was_in to going_to.
   * We redefine this later when we need it. */
  int need_movement = 0;
  /* Contains the "leave" message to display to the was_in room. */
  char leave_message[SMALL_BUFSIZE];
  /*---------------------------------------------------------------------*/
  /* End Local variable definitions */


  /* Begin checks that can prevent a character from leaving the was_in room. */
  /* Future checks should be implemented within this section and return 0.   */
  /*---------------------------------------------------------------------*/
  /* Check for special routines that might activate because of the move and
   * also might prevent the movement. Special requires commands, so we pass
   * in the "command" equivalent of the direction (ie. North is '1' in the
   * command list, but NORTH is defined as '0').
   * Note -- only check if following; this avoids 'double spec-proc' bug */
  if (need_specials_check && special(ch, dir + 1, spec_proc_args))
    return 0;

  /* Leave Trigger Checks: Does a leave trigger block exit from the room? */
  if (!leave_mtrigger(ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;
  if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;
  if (!leave_otrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;

  /* Charm effect: Does it override the movement? */
  if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && was_in == IN_ROOM(ch->master))
  {
    send_to_char(ch, "The thought of leaving your master makes you weep.\r\n");
    act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
    return (0);
  }

  /* Water, No Swimming Rooms: Does the deep water prevent movement? */
  if ((SECT(was_in) == SECT_WATER_NOSWIM) ||
      (SECT(going_to) == SECT_WATER_NOSWIM))
  {
    if (!has_boat(ch))
    {
      send_to_char(ch, "You need a boat to go there.\r\n");
      return (0);
    }
  }

  /* Flying Required: Does lack of flying prevent movement? */
  if ((SECT(was_in) == SECT_FLYING) || (SECT(going_to) == SECT_FLYING))
  {
    if (!has_flight(ch))
    {
      send_to_char(ch, "You need to be flying to go there!\r\n");
      return (0);
    }
  }

  /* Underwater Room: Does lack of underwater breathing prevent movement? */
  if ((SECT(was_in) == SECT_UNDERWATER) || (SECT(going_to) == SECT_UNDERWATER))
  {
    if (!has_scuba(ch) && !IS_NPC(ch) && !PRF_FLAGGED(ch, PRF_NOHASSLE)) {
      send_to_char(ch, "You need to be able to breathe water to go there!\r\n");
      return (0);
    }
  }

  /* Houses: Can the player walk into the house? */
  if (ROOM_FLAGGED(was_in, ROOM_ATRIUM))
  {
    if (!House_can_enter(ch, GET_ROOM_VNUM(going_to)))
    {
      send_to_char(ch, "That's private property -- no trespassing!\r\n");
      return (0);
    }
  }

  /* Check zone level recommendations */
  if ((ZONE_MINLVL(GET_ROOM_ZONE(going_to)) != -1) && ZONE_MINLVL(GET_ROOM_ZONE(going_to)) > GET_LEVEL(ch)) {
    send_to_char(ch, "This zone is above your recommended level.\r\n");
  }

  /* Check zone flag restrictions */
  if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_CLOSED)) {
    send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n");
    return (0);
  }
  if (ZONE_FLAGGED(GET_ROOM_ZONE(going_to), ZONE_NOIMMORT) && (GET_ADMLEVEL(ch) >= ADMLVL_IMMORT) && (GET_ADMLEVEL(ch) < ADMLVL_GRGOD)) {
    send_to_char(ch, "A mysterious barrier forces you back! That area is off-limits.\r\n");
    return (0);
  }

  /* Room Size Capacity: Is the room full of people already? */
  if (ROOM_FLAGGED(going_to, ROOM_TUNNEL) &&
      num_pc_in_room(&(world[going_to])) >= CONFIG_TUNNEL_SIZE)
  {
    if (CONFIG_TUNNEL_SIZE > 1)
      send_to_char(ch, "There isn't enough room for you to go there!\r\n");
    else
      send_to_char(ch, "There isn't enough room there for more than one person!\r\n");
    return (0);
  }

  /* Room Level Requirements: Is ch privileged enough to enter the room? */
  if (ROOM_FLAGGED(going_to, ROOM_GODROOM) && GET_ADMLEVEL(ch) < ADMLVL_GOD)
  {
    send_to_char(ch, "You aren't godly enough to use that room!\r\n");
    return (0);
  }

  /* All checks passed, nothing will prevent movement now other than lack of
   * move points. */
  /* move points needed is avg. move loss for src and destination sect type */
  need_movement = (movement_loss[SECT(was_in)] +
		   movement_loss[SECT(going_to)]) / 2;

  /* Move Point Requirement Check */
  if (GET_MOVE(ch) < need_movement && !IS_NPC(ch))
  {
    if (need_specials_check && ch->master)
      send_to_char(ch, "You are too exhausted to follow.\r\n");
    else
      send_to_char(ch, "You are too exhausted.\r\n");

    return (0);
  }

  /*---------------------------------------------------------------------*/
  /* End checks that can prevent a character from leaving the was_in room. */


  /* Begin: the leave operation. */
  /*---------------------------------------------------------------------*/
  /* If applicable, subtract movement cost. */
  if (GET_ADMLEVEL(ch) < ADMLVL_IMMORT && !IS_NPC(ch))
    GET_MOVE(ch) -= need_movement;

  /* Generate the leave message and display to others in the was_in room. */
  if (!AFF_FLAGGED(ch, AFF_SNEAK))
  {
    snprintf(leave_message, sizeof(leave_message), "$n leaves %s.", dirs[dir]);
    act(leave_message, TRUE, ch, 0, 0, TO_ROOM);
  }

  char_from_room(ch);
  char_to_room(ch, going_to);
  /*---------------------------------------------------------------------*/
  /* End: the leave operation. The character is now in the new room. */


  /* Begin: Post-move operations. */
  /*---------------------------------------------------------------------*/
  /* Post Move Trigger Checks: Check the new room for triggers.
   * Assumptions: The character has already truly left the was_in room. If
   * the entry trigger "prevents" movement into the room, it is the triggers
   * job to provide a message to the original was_in room. */
  if (!entry_mtrigger(ch) || !enter_wtrigger(&world[going_to], ch, dir)) {
    char_from_room(ch);
    char_to_room(ch, was_in);
    return 0;
  }

  /* Display arrival information to anyone in the destination room... */
  if (!AFF_FLAGGED(ch, AFF_SNEAK))
    act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);

  /* ... and the room description to the character. */
  if (ch->desc != NULL)
    look_at_room(ch, 0);

  /* ... and Kill the player if the room is a death trap. */
  if (ROOM_FLAGGED(going_to, ROOM_DEATH) && GET_ADMLEVEL(ch) < ADMLVL_IMMORT)
  {
    mudlog(BRF, ADMLVL_IMMORT, TRUE, "%s hit death trap #%d (%s)", GET_NAME(ch), GET_ROOM_VNUM(going_to), world[going_to].name);
    death_cry(ch);
    extract_char(ch);
    return (0);
  }

  /* At this point, the character is safe and in the room. */
  /* Fire memory and greet triggers, check and see if the greet trigger
   * prevents movement, and if so, move the player back to the previous room. */
  entry_memory_mtrigger(ch);
  if (!greet_mtrigger(ch, dir))
  {
    char_from_room(ch);
    char_to_room(ch, was_in);
    look_at_room(ch, 0);
    /* Failed move, return a failure */
    return (0);
  }
  else
    greet_memory_mtrigger(ch);
  /*---------------------------------------------------------------------*/
  /* End: Post-move operations. */

  /* Only here is the move successful *and* complete. Return success for
   * calling functions to handle post move operations. */
  return (1);
}
Beispiel #13
0
zone_rnum create_new_zone(zone_vnum vzone_num, room_vnum bottom, room_vnum top, const char **error)
{
  FILE *fp;
  struct zone_data *zone;
  int i;
  zone_rnum rznum;
  char buf[MAX_STRING_LENGTH];

#if CIRCLE_UNSIGNED_INDEX
  if (vzone_num == NOWHERE) {
#else
  if (vzone_num < 0) {
#endif
    *error = "You can't make negative zones.\r\n";
    return NOWHERE;
  } else if (bottom > top) {
    *error = "Bottom room cannot be greater than top room.\r\n";
    return NOWHERE;
  }

#if _CIRCLEMUD < CIRCLEMUD_VERSION(3,0,21)
  /*
   * New with bpl19, the OLC interface should decide whether
   * to allow overlap before calling this function. There
   * are more complicated rules for that but it's not covered
   * here.
   */
  if (vzone_num > 326) {
    *error = "326 is the highest zone allowed.\r\n";
    return NOWHERE;
  }

  /*
   * Make sure the zone does not exist.
   */
  room = vzone_num * 100; /* Old CircleMUD 100-zones. */
  for (i = 0; i <= top_of_zone_table; i++)
    if (genolc_zone_bottom(i) <= room && zone_table[i].top >= room) {
      *error = "A zone already covers that area.\r\n";
      return NOWHERE;
    }
#else
  for (i = 0; i < top_of_zone_table; i++)
    if (zone_table[i].number == vzone_num) {
      *error = "That virtual zone already exists.\r\n";
      return NOWHERE;
     }
#endif

  /*
   * Create the zone file.
   */
  snprintf(buf, sizeof(buf), "%s%d.zon", ZON_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new zone file.");
    *error = "Could not write zone file.\r\n";
    return NOWHERE;
  }
#if _CIRCLEMUD >= CIRCLEMUD_VERSION(3,0,21)
  /* File format changed. */
  fprintf(fp, "#%d\nNone~\nNew Zone~\n%d %d 30 2\nS\n$\n", vzone_num, bottom, top);
#else
  fprintf(fp, "#%d\nNew Zone~\n%d 30 2\nS\n$\n", vzone_num, (vzone_num * 100) + 99);
#endif
  fclose(fp);

  /*
   * Create the room file.
   */
  snprintf(buf, sizeof(buf), "%s%d.wld", WLD_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new world file.");
    *error = "Could not write world file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "#%d\nThe Beginning~\nNot much here.\n~\n%d 0 0\nS\n$\n", bottom, vzone_num);
  fclose(fp);

  /*
   * Create the mobile file.
   */
  snprintf(buf, sizeof(buf), "%s%d.mob", MOB_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new mob file.");
    *error = "Could not write mobile file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "$\n");
  fclose(fp);

  /*
   * Create the object file.
   */
  snprintf(buf, sizeof(buf), "%s%d.obj", OBJ_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new obj file.");
    *error = "Could not write object file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "$\n");
  fclose(fp);

  /*
   * Create the shop file.
   */
  snprintf(buf, sizeof(buf), "%s%d.shp", SHP_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new shop file.");
    *error = "Could not write shop file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "$~\n");
  fclose(fp);

  /*
   * Create the trigger file.
   */
  snprintf(buf, sizeof(buf), "%s%d.trg", TRG_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new trigger file");
    *error = "Could not write trigger file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "$~\n");
  fclose(fp);

  /*
   * Create Gld file .
   */
  snprintf(buf, sizeof(buf), "%s/%i.gld", GLD_PREFIX, vzone_num);
  if (!(fp = fopen(buf, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Can't write new guild file");
    *error = "Could not write guild file.\r\n";
    return NOWHERE;
  }
  fprintf(fp, "$~\n");
  fclose(fp);

  /*
   * Update index files.
   */
  create_world_index(vzone_num, "zon");
  create_world_index(vzone_num, "wld");
  create_world_index(vzone_num, "mob");
  create_world_index(vzone_num, "obj");
  create_world_index(vzone_num, "shp");
  create_world_index(vzone_num, "trg");
  create_world_index(vzone_num, "gld");
  
  /*
   * Make a new zone in memory. This was the source of all the zedit new
   * crashes reported to the CircleMUD list. It was happily overwriting
   * the stack.  This new loop by Andrew Helm fixes that problem and is
   * more understandable at the same time.
   *
   * The variable is 'top_of_zone_table_table + 2' because we need record 0
   * through top_of_zone (top_of_zone_table + 1 items) and a new one which
   * makes it top_of_zone_table + 2 elements large.
   */
  RECREATE(zone_table, struct zone_data, top_of_zone_table + 2);
  zone_table[top_of_zone_table + 1].number = 32000;

  if (vzone_num > zone_table[top_of_zone_table].number)
    rznum = top_of_zone_table + 1;
  else {
    int j, room;
    for (i = top_of_zone_table + 1; i > 0 && vzone_num < zone_table[i - 1].number; i--) {
      zone_table[i] = zone_table[i - 1];
      for (j = zone_table[i].bot; j <= zone_table[i].top; j++)
        if ((room = real_room(j)) != NOWHERE)
          world[room].zone++;
    } 
    rznum = i;
  }
  zone = &zone_table[rznum];

  /*
   * Ok, insert the new zone here.
   */  
  zone->name = strdup("New Zone");
  zone->number = vzone_num;
  zone->builders = strdup("None");
#if _CIRCLEMUD >= CIRCLEMUD_VERSION(3,0,21)
  zone->bot = bottom;
  zone->top = top;
#else
  zone->top = (vzone_num * 100) + 99;
#endif
  zone->lifespan = 30;
  zone->age = 0;
  zone->reset_mode = 2;
  zone->zone_flags[0] = 0;
  zone->zone_flags[1] = 0;
  zone->zone_flags[2] = 0;
  zone->zone_flags[3] = 0;
  zone->min_level = 0;
  zone->max_level = LVL_IMPL;
  /*
   * No zone commands, just terminate it with an 'S'
   */
  CREATE(zone->cmd, struct reset_com, 1);
  zone->cmd[0].command = 'S';

  top_of_zone_table++;

  for (i = top_of_world; i > 0; i--)
    if (world[i].zone < real_zone(rznum))
      break;
    else
      world[i].zone = real_zone_by_thing(GET_ROOM_VNUM(i)); 

  add_to_save_list(zone->number, SL_ZON);
  return rznum;
}

/*-------------------------------------------------------------------*/

void create_world_index(int znum, const char *type)
{
  FILE *newfile, *oldfile;
  char new_name[32], old_name[32], *prefix;
  int num, found = FALSE;
  char buf[MAX_STRING_LENGTH];
  char buf1[MAX_STRING_LENGTH];

  switch (*type) {
  case 'z':
    prefix = ZON_PREFIX;
    break;
  case 'w':
    prefix = WLD_PREFIX;
    break;
  case 'o':
    prefix = OBJ_PREFIX;
    break;
  case 'm':
    prefix = MOB_PREFIX;
    break;
  case 's':
    prefix = SHP_PREFIX;
    break;
  case 't':
    prefix = TRG_PREFIX;
    break;
  case 'g':
    prefix = GLD_PREFIX;
    break;
  default:
    /*
     * Caller messed up  
     */
    return;
  }

  snprintf(old_name, sizeof(old_name), "%s/index", prefix);
  snprintf(new_name, sizeof(new_name), "%s/newindex", prefix);

  if (!(oldfile = fopen(old_name, "r"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", old_name);
    return;
  } else if (!(newfile = fopen(new_name, "w"))) {
    mudlog(BRF, LVL_IMPL, TRUE, "SYSERR: OLC: Failed to open %s.", new_name);
    fclose(oldfile);
    return;
  }

  /*
   * Index contents must be in order: search through the old file for the
   * right place, insert the new file, then copy the rest over. 
   */
  snprintf(buf1, sizeof(buf1), "%d.%s", znum, type);
  while (get_line(oldfile, buf)) {
    if (*buf == '$') {
      /*
       * The following used to add a blank line, thanks to Brian Taylor for the fix... (Mythran)
       */
      fprintf(newfile, "%s", (!found ? strncat(buf1, "\n$\n", sizeof(buf1)-1) : "$\n"));
      break;
    } else if (!found) {
      sscanf(buf, "%d", &num);
      if (num == znum) {
        found = TRUE;
      } else if (num > znum) {
	found = TRUE;
	fprintf(newfile, "%s\n", buf1);
      }
    }
    fprintf(newfile, "%s\n", buf);
  }

  fclose(newfile);
  fclose(oldfile);
  /*
   * Out with the old, in with the new.
   */
  remove(old_name);
  rename(new_name, old_name);
}
Beispiel #14
0
/* do_simple_move assumes that there is no master, no followers and that the
 * direction exists. It returns 1 for success, 0 if failure. */
int do_simple_move(struct char_data *ch, int dir, int need_specials_check)
{
  char throwaway[MAX_INPUT_LENGTH] = ""; /* Functions assume writable. */
  room_rnum was_in = IN_ROOM(ch);
  int need_movement;

  /* Check for special routines (North is 1 in command list, but 0 here) Note
   * -- only check if following; this avoids 'double spec-proc' bug */
  if (need_specials_check && special(ch, dir + 1, throwaway))
    return (0);

  /* blocked by a leave trigger ? */
  if (!leave_mtrigger(ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;
  if (!leave_wtrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;
  if (!leave_otrigger(&world[IN_ROOM(ch)], ch, dir) || IN_ROOM(ch) != was_in) /* prevent teleport crashes */
    return 0;
  /* charmed? */
  if (AFF_FLAGGED(ch, AFF_CHARM) && ch->master && IN_ROOM(ch) == IN_ROOM(ch->master)) {
    send_to_char(ch, "The thought of leaving your master makes you weep.\r\n");
    act("$n bursts into tears.", FALSE, ch, 0, 0, TO_ROOM);
    return (0);
  }

  /* if this room or the one we're going to needs a boat, check for one */
  if ((SECT(IN_ROOM(ch)) == SECT_WATER_NOSWIM) ||
      (SECT(EXIT(ch, dir)->to_room) == SECT_WATER_NOSWIM)) {
    if (!has_boat(ch)) {
      send_to_char(ch, "You need a boat to go there.\r\n");
      return (0);
    }
  }

  /* If this room or the one we're going to needs flight, check for it. */
  if ((SECT(IN_ROOM(ch)) == SECT_FLYING) || (SECT(EXIT(ch, dir)->to_room) == SECT_FLYING)) {
    if (!has_flight(ch)) {
      send_to_char(ch, "You need to be flying to go there!\r\n");
      return (0);
    }
  }

  /* If this room or the one we're going to needs scuba, check for it. */
  if ((SECT(IN_ROOM(ch)) == SECT_UNDERWATER) || (SECT(EXIT(ch, dir)->to_room) == SECT_UNDERWATER)) {
    if (!has_scuba(ch)) {
      send_to_char(ch, "You need to be able to breathe water to go there!\r\n");
      return (0);
    }
  }

  /* move points needed is avg. move loss for src and destination sect type */
  need_movement = (movement_loss[SECT(IN_ROOM(ch))] +
		   movement_loss[SECT(EXIT(ch, dir)->to_room)]) / 2;

  if (GET_MOVE(ch) < need_movement && !IS_NPC(ch)) {
    if (need_specials_check && ch->master)
      send_to_char(ch, "You are too exhausted to follow.\r\n");
    else
      send_to_char(ch, "You are too exhausted.\r\n");

    return (0);
  }
  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_ATRIUM)) {
    if (!House_can_enter(ch, GET_ROOM_VNUM(EXIT(ch, dir)->to_room))) {
      send_to_char(ch, "That's private property -- no trespassing!\r\n");
      return (0);
    }
  }
  if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_TUNNEL) &&
      num_pc_in_room(&(world[EXIT(ch, dir)->to_room])) >= CONFIG_TUNNEL_SIZE) {
    if (CONFIG_TUNNEL_SIZE > 1)
      send_to_char(ch, "There isn't enough room for you to go there!\r\n");
    else
      send_to_char(ch, "There isn't enough room there for more than one person!\r\n");
    return (0);
  }
  /* Mortals and low level gods cannot enter greater god rooms. */
  if (ROOM_FLAGGED(EXIT(ch, dir)->to_room, ROOM_GODROOM) &&
	GET_LEVEL(ch) < LVL_GOD) {
    send_to_char(ch, "You aren't godly enough to use that room!\r\n");
    return (0);
  }

  /* Now we know we're allowed to go into the room. */
  if (GET_LEVEL(ch) < LVL_IMMORT && !IS_NPC(ch))
    GET_MOVE(ch) -= need_movement;

  if (!AFF_FLAGGED(ch, AFF_SNEAK)) {
    char buf2[MAX_STRING_LENGTH];

    snprintf(buf2, sizeof(buf2), "$n leaves %s.", dirs[dir]);
    act(buf2, TRUE, ch, 0, 0, TO_ROOM);
  }
  was_in = IN_ROOM(ch);
  char_from_room(ch);
  char_to_room(ch, world[was_in].dir_option[dir]->to_room);

  /* move them first, then move them back if they aren't allowed to go. Also,
   * see if an entry trigger disallows the move */
  if (!entry_mtrigger(ch) || !enter_wtrigger(&world[IN_ROOM(ch)], ch, dir)) {
    char_from_room(ch);
    char_to_room(ch, was_in);
    return 0;
  }

  if (!AFF_FLAGGED(ch, AFF_SNEAK))
    act("$n has arrived.", TRUE, ch, 0, 0, TO_ROOM);

  if (ch->desc != NULL)
    look_at_room(ch, 0);

  if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_DEATH) && GET_LEVEL(ch) < LVL_IMMORT) {
    mudlog(BRF, LVL_IMMORT, TRUE, "%s hit death trap #%d (%s)", GET_NAME(ch), GET_ROOM_VNUM(IN_ROOM(ch)), world[IN_ROOM(ch)].name);
    death_cry(ch);
    extract_char(ch);
    return (0);
  }

  entry_memory_mtrigger(ch);
  if (!greet_mtrigger(ch, dir)) {
    char_from_room(ch);
    char_to_room(ch, was_in);
    look_at_room(ch, 0);
  } else greet_memory_mtrigger(ch);

  return (1);
}
Beispiel #15
0
int gen_receptionist(struct char_data *ch, struct char_data *recep,
		         int cmd, char *arg, int mode)
{
  int cost;
  const char *action_table[] = { "smile", "dance", "sigh", "blush", "burp",
	  "cough", "fart", "twiddle", "yawn" };

  if (!cmd && !rand_number(0, 5)) {
    do_action(recep, NULL, find_command(action_table[rand_number(0, 8)]), 0);
    return (FALSE);
  }

  if (!ch->desc || IS_NPC(ch))
    return (FALSE);

  if (!CMD_IS("offer") && !CMD_IS("rent"))
    return (FALSE);

  if (!AWAKE(recep)) {
    send_to_char(ch, "%s is unable to talk to you...\r\n", HSSH(recep));
    return (TRUE);
  }

  if (!CAN_SEE(recep, ch)) {
    act("$n says, 'I don't deal with people I can't see!'", FALSE, recep, 0, 0, TO_ROOM);
    return (TRUE);
  }

  if (free_rent) {
    act("$n tells you, 'Rent is free here.  Just quit, and your objects will be saved!'",
	FALSE, recep, 0, ch, TO_VICT);
    return (1);
  }

  if (CMD_IS("rent")) {
    char buf[128];

    if (!(cost = Crash_offer_rent(ch, recep, FALSE, mode)))
      return (TRUE);
    if (mode == RENT_FACTOR)
      snprintf(buf, sizeof(buf), "$n tells you, 'Rent will cost you %d gold coins per day.'", cost);
    else if (mode == CRYO_FACTOR)
      snprintf(buf, sizeof(buf), "$n tells you, 'It will cost you %d gold coins to be frozen.'", cost);
    act(buf, FALSE, recep, 0, ch, TO_VICT);

    if (cost > GET_GOLD(ch) + GET_BANK_GOLD(ch)) {
      act("$n tells you, '...which I see you can't afford.'",
	  FALSE, recep, 0, ch, TO_VICT);
      return (TRUE);
    }
    if (cost && (mode == RENT_FACTOR))
      Crash_rent_deadline(ch, recep, cost);

    if (mode == RENT_FACTOR) {
      act("$n stores your belongings and helps you into your private chamber.", FALSE, recep, 0, ch, TO_VICT);
      Crash_rentsave(ch, cost);
      mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s has rented (%d/day, %d tot.)",
		GET_NAME(ch), cost, GET_GOLD(ch) + GET_BANK_GOLD(ch));
    } else {			/* cryo */
      act("$n stores your belongings and helps you into your private chamber.\r\n"
	  "A white mist appears in the room, chilling you to the bone...\r\n"
	  "You begin to lose consciousness...",
	  FALSE, recep, 0, ch, TO_VICT);
      Crash_cryosave(ch, cost);
      mudlog(NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(ch)), TRUE, "%s has cryo-rented.", GET_NAME(ch));
      SET_BIT(PLR_FLAGS(ch), PLR_CRYO);
    }

    act("$n helps $N into $S private chamber.", FALSE, recep, 0, ch, TO_NOTVICT);

    GET_LOADROOM(ch) = GET_ROOM_VNUM(IN_ROOM(ch));
    extract_char(ch);	/* It saves. */
  } else {
    Crash_offer_rent(ch, recep, TRUE, mode);
    act("$N gives $n an offer.", FALSE, ch, 0, recep, TO_ROOM);
  }
  return (TRUE);
}
/**
* WARNING: This function actually deletes a building.
*
* @param char_data *ch The person doing the deleting.
* @param bld_vnum vnum The vnum to delete.
*/
void olc_delete_building(char_data *ch, bld_vnum vnum) {
	void check_for_bad_buildings();
	extern bool delete_link_rule_by_type_value(struct adventure_link_rule **list, int type, any_vnum value);
	void remove_building_from_table(bld_data *bld);
	
	descriptor_data *desc;
	room_data *room, *next_room;
	craft_data *craft, *next_craft;
	adv_data *adv, *next_adv;
	bld_data *bld;
	int count;
	bool found, deleted = FALSE;
	
	if (!(bld = building_proto(vnum))) {
		msg_to_char(ch, "There is no such building %d.\r\n", vnum);
		return;
	}
	
	if (HASH_COUNT(building_table) <= 1) {
		msg_to_char(ch, "You can't delete the last building.\r\n");
		return;
	}
	
	// pull from hash
	remove_building_from_table(bld);

	// save index and building file now
	save_index(DB_BOOT_BLD);
	save_library_file_for_vnum(DB_BOOT_BLD, vnum);
	
	// update world
	count = 0;
	HASH_ITER(world_hh, world_table, room, next_room) {
		if (IS_ANY_BUILDING(room) && BUILDING_VNUM(room) == vnum) {
			if (GET_ROOM_VNUM(room) >= MAP_SIZE) {
				delete_room(room, FALSE);	// must call check_all_exits
				deleted = TRUE;
			}
			else {
				// map room
				if (ROOM_PEOPLE(room)) {
					act("The building has been deleted.", FALSE, ROOM_PEOPLE(room), NULL, NULL, TO_CHAR | TO_ROOM);
				}
				disassociate_building(room);
			}
		}
	}
	if (deleted) {
		check_all_exits();
	}
	
	// adventure zones
	HASH_ITER(hh, adventure_table, adv, next_adv) {
		found = delete_link_rule_by_type_value(&GET_ADV_LINKING(adv), ADV_LINK_BUILDING_EXISTING, vnum);
		found |= delete_link_rule_by_type_value(&GET_ADV_LINKING(adv), ADV_LINK_BUILDING_NEW, vnum);
		found |= delete_link_rule_by_type_value(&GET_ADV_LINKING(adv), ADV_LINK_PORTAL_BUILDING_EXISTING, vnum);
		found |= delete_link_rule_by_type_value(&GET_ADV_LINKING(adv), ADV_LINK_PORTAL_BUILDING_NEW, vnum);
		
		if (found) {
			save_library_file_for_vnum(DB_BOOT_ADV, GET_ADV_VNUM(adv));
		}
	}