Example #1
0
void top_level_diversion::output(node *nd, int retain_size,
				 vunits vs, vunits post_vs, hunits width)
{
  no_space_mode = 0;
  vunits next_trap_pos;
  trap *next_trap = find_next_trap(&next_trap_pos);
  if (before_first_page && begin_page()) 
    fatal("sorry, I didn't manage to begin the first page in time: use an explicit .br request");
  vertical_size v(vs, post_vs);
  for (node *tem = nd; tem != 0; tem = tem->next)
    tem->set_vertical_size(&v);
  last_post_line_extra_space = v.post_extra.to_units();
  if (!retain_size) {
    v.pre = vs;
    v.post = post_vs;
  }
  vertical_position += v.pre;
  vertical_position += v.pre_extra;
  the_output->print_line(page_offset, vertical_position, nd,
			 v.pre + v.pre_extra, v.post_extra, width);
  vertical_position += v.post_extra;
  if (vertical_position > high_water_mark)
    high_water_mark = vertical_position;
  if (vertical_position_traps_flag && vertical_position >= page_length)
    begin_page();
  else if (vertical_position_traps_flag
	   && next_trap != 0 && vertical_position >= next_trap_pos) {
    nl_reg_contents = vertical_position.to_units();
    truncated_space = v.post;
    spring_trap(next_trap->nm);
  }
  else if (v.post > V0) {
    vertical_position += v.post;
    if (vertical_position_traps_flag
	&& next_trap != 0 && vertical_position >= next_trap_pos) {
      truncated_space = vertical_position - next_trap_pos;
      vertical_position = next_trap_pos;
      nl_reg_contents = vertical_position.to_units();
      spring_trap(next_trap->nm);
    }
    else if (vertical_position_traps_flag && vertical_position >= page_length)
      begin_page();
    else
      nl_reg_contents = vertical_position.to_units();
  }
  else
    nl_reg_contents = vertical_position.to_units();
}
Example #2
0
void top_level_diversion::space(vunits n, int forced)
{
  if (no_space_mode) {
    if (!forced)
      return;
    else
      no_space_mode = 0;
  }
  if (before_first_page) {
    begin_page(n);
    return;
  }
  vunits next_trap_pos;
  trap *next_trap = find_next_trap(&next_trap_pos);
  vunits y = vertical_position + n;
  if (curenv->get_vertical_spacing().to_units())
    curenv->seen_space += n.to_units()
			  / curenv->get_vertical_spacing().to_units();
  if (vertical_position_traps_flag && next_trap != 0 && y >= next_trap_pos) {
    vertical_position = next_trap_pos;
    nl_reg_contents = vertical_position.to_units();
    truncated_space = y - vertical_position;
    spring_trap(next_trap->nm);
  }
  else if (y < V0) {
    vertical_position = V0;
    nl_reg_contents = vertical_position.to_units();
  }
  else if (vertical_position_traps_flag && y >= page_length && n >= V0)
    begin_page(y - page_length);
  else {
    vertical_position = y;
    nl_reg_contents = vertical_position.to_units();
  }
}
Example #3
0
/**
 * Try to disarm a trap.
 * @param disarmer Player disarming the trap.
 * @param trap Trap to disarm.
 * @return 1 if trap was disarmed, 0 otherwise. */
int trap_disarm(object *disarmer, object *trap)
{
	object *env = trap->env;
	int disarmer_level = CONTR(disarmer)->exp_ptr[EXP_AGILITY]->level;

	if ((trap->level <= disarmer_level && rndm_chance(10)) || !(rndm(0, (MAX(2, MIN(20, trap->level - disarmer_level + 5 - disarmer->stats.Dex / 2)) - 1))))
	{
		new_draw_info_format(NDI_UNIQUE, disarmer, "You successfuly remove the %s (lvl %d)!", trap->name, trap->level);
		remove_ob(trap);
		check_walk_off(trap, NULL, MOVE_APPLY_VANISHED);
		set_trapped_flag(env);
		return 1;
	}
	else
	{
		new_draw_info_format(NDI_UNIQUE, disarmer, "You fail to remove the %s (lvl %d).", trap->name, trap->level);

		if (trap->level > disarmer_level * 1.4f || rndm(0, 2))
		{
			if (!(rndm(0, (MAX(2, disarmer_level - trap->level + disarmer->stats.Dex / 2 - 6)) - 1)))
			{
				new_draw_info(NDI_UNIQUE, disarmer, "In fact, you set it off!");
				spring_trap(trap, disarmer);
			}
		}

		return 0;
	}
}
Example #4
0
void macro_diversion::space(vunits n, int)
{
  if (vertical_position_traps_flag
      && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
      && diversion_trap_pos <= vertical_position + n) {
    truncated_space = vertical_position + n - diversion_trap_pos;
    n = diversion_trap_pos - vertical_position;
    spring_trap(diversion_trap);
  }
  else if (n + vertical_position < V0)
    n = -vertical_position;
  mac->append(new diverted_space_node(n));
  vertical_position += n;
}
Example #5
0
// Returns non-zero if it sprung a top-of-page trap.
// The optional parameter is for the .trunc register.
int top_level_diversion::begin_page(vunits n)
{
  if (exit_started) {
    if (page_count == last_page_count
	? curenv->is_empty()
	: (done_end_macro && (seen_last_page_ejector || began_page_in_end_macro)))
      cleanup_and_exit(0);
    if (!done_end_macro)
      began_page_in_end_macro = 1;
  }
  if (last_page_number > 0 && page_number == last_page_number)
    cleanup_and_exit(0);
  if (!the_output)
    init_output();
  ++page_count;
  if (have_next_page_number) {
    page_number = next_page_number;
    have_next_page_number = 0;
  }
  else if (before_first_page == 1)
    page_number = 1;
  else
    page_number++;
  // spring the top of page trap if there is one
  vunits next_trap_pos;
  vertical_position = -vresolution;
  trap *next_trap = find_next_trap(&next_trap_pos);
  vertical_position = V0;
  high_water_mark = V0;
  ejecting_page = 0;
  // If before_first_page was 2, then the top of page transition was undone
  // using eg .nr nl 0-1.  See nl_reg::set_value.
  if (before_first_page != 2)
    the_output->begin_page(page_number, page_length);
  before_first_page = 0;
  nl_reg_contents = vertical_position.to_units();
  if (vertical_position_traps_flag && next_trap != 0 && next_trap_pos == V0) {
    truncated_space = n;
    spring_trap(next_trap->nm);
    return 1;
  }
  else
    return 0;
}
Example #6
0
void macro_diversion::output(node *nd, int retain_size,
			     vunits vs, vunits post_vs, hunits width)
{
  no_space_mode = 0;
  vertical_size v(vs, post_vs);
  while (nd != 0) {
    nd->set_vertical_size(&v);
    node *temp = nd;
    nd = nd->next;
    if (temp->interpret(mac))
      delete temp;
    else {
#if 1
      temp->freeze_space();
#endif
      mac->append(temp);
    }
  }
  last_post_line_extra_space = v.post_extra.to_units();
  if (!retain_size) {
    v.pre = vs;
    v.post = post_vs;
  }
  if (width > max_width)
    max_width = width;
  vunits x = v.pre + v.pre_extra + v.post + v.post_extra;
  if (vertical_position_traps_flag
      && !diversion_trap.is_null() && diversion_trap_pos > vertical_position
      && diversion_trap_pos <= vertical_position + x) {
    vunits trunc = vertical_position + x - diversion_trap_pos;
    if (trunc > v.post)
      trunc = v.post;
    v.post -= trunc;
    x -= trunc;
    truncated_space = trunc;
    spring_trap(diversion_trap);
  }
  mac->append(new vertical_size_node(-v.pre));
  mac->append(new vertical_size_node(v.post));
  mac->append('\n');
  vertical_position += x;
  if (vertical_position - v.post > high_water_mark)
    high_water_mark = vertical_position - v.post;
}
Example #7
0
/*
 * Check an object for a trap - Thoric
 */
ch_ret check_for_trap( char_data * ch, obj_data * obj, int flag )
{
   if( obj->contents.empty(  ) )
      return rNONE;

   ch_ret retcode = rNONE;
   list < obj_data * >::iterator iobj;
   for( iobj = obj->contents.begin(  ); iobj != obj->contents.end(  ); ++iobj )
   {
      obj_data *check = *iobj;

      if( check->item_type == ITEM_TRAP && IS_SET( check->value[3], flag ) )
      {
         retcode = spring_trap( ch, check );
         if( retcode != rNONE )
            return retcode;
      }
   }
   return retcode;
}
Example #8
0
/*
 * Check the room for a trap - Thoric
 */
ch_ret check_room_for_traps( char_data * ch, int flag )
{
   if( !ch )
      return rERROR;
   if( !ch->in_room || ch->in_room->objects.empty(  ) )
      return rNONE;

   ch_ret retcode = rNONE;
   list < obj_data * >::iterator iobj;
   for( iobj = ch->in_room->objects.begin(  ); iobj != ch->in_room->objects.end(  ); ++iobj )
   {
      obj_data *check = *iobj;
      if( check->item_type == ITEM_TRAP && IS_SET( check->value[3], flag ) )
      {
         retcode = spring_trap( ch, check );
         if( retcode != rNONE )
            return retcode;
      }
   }
   return retcode;
}
Example #9
0
File: apply.c Project: atrinik/dwc
/**
 * 'victim' moves onto 'trap' (trap has FLAG_WALK_ON or FLAG_FLY_ON set) or
 * 'victim' leaves 'trap' (trap has FLAG_WALK_OFF or FLAG_FLY_OFF) set.
 *
 * I added the flags parameter to give the single events more information
 * about whats going on:
 *
 * Most important is the "MOVE_APPLY_VANISHED" flag.
 * If set, a object has left a tile but "vanished" and not moved (perhaps
 * it exploded or something). This means that some events are not
 * triggered like trapdoors or teleporter traps for example which have a
 * "FLY/MOVE_OFF" set. This will avoid that they touch invalid objects.
 * @param trap Object victim moved on.
 * @param victim The object that moved on trap.
 * @param originator Player, monster or other object that caused 'victim'
 * to move onto 'trap'. Will receive messages caused by this action. May
 * be NULL, however, some types of traps require an originator to
 * function.
 * @param flags Flags. */
void move_apply(object *trap, object *victim, object *originator, int flags)
{
	static int recursion_depth = 0;

	/* move_apply() is the most likely candidate for causing unwanted and
	 * possibly unlimited recursion. */
	/* The following was changed because it was causing perfeclty correct
	 * maps to fail.  1)  it's not an error to recurse:
	 * rune detonates, summoning monster.  monster lands on nearby rune.
	 * nearby rune detonates.  This sort of recursion is expected and
	 * proper.  This code was causing needless crashes. */
	if (recursion_depth >= 500)
	{
		LOG(llevDebug, "WARNING: move_apply(): aborting recursion [trap arch %s, name %s; victim arch %s, name %s]\n", trap->arch->name, trap->name, victim->arch->name, victim->name);
		return;
	}

	if (trap->head)
	{
		trap = trap->head;
	}

	/* Trigger the TRIGGER event */
	if (trigger_event(EVENT_TRIGGER, victim, trap, originator, NULL, 0, 0, 0, SCRIPT_FIX_NOTHING))
	{
		return;
	}

	recursion_depth++;

	switch (trap->type)
	{
		/* these objects can trigger other objects connected to them.
		 * We need to check them at map loading time and other special
		 * events to be sure to have a 100% working map state. */
		case BUTTON:
		case PEDESTAL:
			update_button(trap);
			break;

		case TRIGGER_BUTTON:
		case TRIGGER_PEDESTAL:
		case TRIGGER_ALTAR:
			check_trigger(trap, victim);
			break;

		case CHECK_INV:
			check_inv(victim, trap);
			break;

		/* these objects trigger to but they are "instant".
		 * We don't need to check them when loading. */
		case ALTAR:
			/* sacrifice victim on trap */
			apply_altar(trap, victim, originator);
			break;

		case CONVERTER:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				convert_item(victim, trap);
			}

			break;

		case PLAYERMOVER:
			break;

		/* should be walk_on/fly_on only */
		case SPINNER:
			if (victim->direction)
			{
				if ((victim->direction = victim->direction + trap->direction) > 8)
				{
					victim->direction = (victim->direction % 8) + 1;
				}

				update_turn_face(victim);
			}

			break;

		case DIRECTOR:
			if (victim->direction)
			{
				victim->direction = trap->direction;
				update_turn_face(victim);
			}

			break;

		/* no need to hit anything */
		case MMISSILE:
			if (IS_LIVE(victim) && !(flags&MOVE_APPLY_VANISHED))
			{
				tag_t trap_tag = trap->count;
				hit_player(victim, trap->stats.dam, trap, AT_MAGIC);

				if (!was_destroyed(trap, trap_tag))
				{
					remove_ob(trap);
				}

				check_walk_off(trap, NULL, MOVE_APPLY_VANISHED);
			}

			break;

		case THROWN_OBJ:
			if (trap->inv == NULL || (flags & MOVE_APPLY_VANISHED))
			{
				break;
			}

		/* fallthrough */
		case ARROW:
			/* bad bug: monster throw a object, make a step forwards, step on object ,
			 * trigger this here and get hit by own missile - and will be own enemy.
			 * Victim then is his own enemy and will start to kill herself (this is
			 * removed) but we have not synced victim and his missile. To avoid senseless
			 * action, we avoid hits here */
			if ((IS_LIVE(victim) && trap->speed) && trap->owner != victim)
			{
				hit_with_arrow(trap, victim);
			}

			break;

		case CONE:
		case LIGHTNING:
			break;

		case BULLET:
			if ((QUERY_FLAG(victim, FLAG_NO_PASS) || IS_LIVE(victim)) && !(flags & MOVE_APPLY_VANISHED))
			{
				check_fired_arch(trap);
			}

			break;

		case TRAPDOOR:
		{
			int max, sound_was_played;
			object *ab;

			if ((flags & MOVE_APPLY_VANISHED))
			{
				break;
			}

			if (!trap->value)
			{
				sint32 tot;

				for (ab = trap->above, tot = 0; ab != NULL; ab = ab->above)
				{
					if (!QUERY_FLAG(ab, FLAG_FLYING))
					{
						tot += (ab->nrof ? ab->nrof : 1) * ab->weight + ab->carrying;
					}
				}

				if (!(trap->value = (tot > trap->weight) ? 1 : 0))
				{
					break;
				}

				SET_ANIMATION(trap, (NUM_ANIMATIONS(trap) / NUM_FACINGS(trap)) * trap->direction + trap->value);
				update_object(trap, UP_OBJ_FACE);
			}

			for (ab = trap->above, max = 100, sound_was_played = 0; --max && ab && !QUERY_FLAG(ab, FLAG_FLYING); ab = ab->above)
			{
				if (!sound_was_played)
				{
					play_sound_map(trap->map, trap->x, trap->y, SOUND_FALL_HOLE, SOUND_NORMAL);
					sound_was_played = 1;
				}

				if (ab->type == PLAYER)
				{
					new_draw_info(NDI_UNIQUE, ab, "You fall into a trapdoor!");
				}

				transfer_ob(ab, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, ab, trap);
			}

			break;
		}


		case PIT:
			/* Pit not open? */
			if ((flags & MOVE_APPLY_VANISHED) || trap->stats.wc > 0)
			{
				break;
			}

			play_sound_map(victim->map, victim->x, victim->y, SOUND_FALL_HOLE, SOUND_NORMAL);

			if (victim->type == PLAYER)
			{
				new_draw_info(NDI_UNIQUE, victim, "You fall through the hole!\n");
			}

			transfer_ob(victim->head ? victim->head : victim, EXIT_X(trap), EXIT_Y(trap), trap->last_sp, victim, trap);

			break;

		case EXIT:
			/* If no map path specified, we assume it is the map path of the exit. */
			if (!EXIT_PATH(trap))
			{
				FREE_AND_ADD_REF_HASH(EXIT_PATH(trap), trap->map->path);
			}

			if (!(flags & MOVE_APPLY_VANISHED) && victim->type == PLAYER && EXIT_PATH(trap) && EXIT_Y(trap) != -1 && EXIT_X(trap) != -1)
			{
				/* Basically, don't show exits leading to random maps the players output. */
				if (trap->msg && strncmp(EXIT_PATH(trap), "/!", 2) && strncmp(EXIT_PATH(trap), "/random/", 8))
				{
					new_draw_info(NDI_NAVY, victim, trap->msg);
				}

				enter_exit(victim, trap);
			}

			break;

		case SHOP_MAT:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				apply_shop_mat(trap, victim);
			}

			break;

		/* Drop a certain amount of gold, and have one item identified */
		case IDENTIFY_ALTAR:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				apply_identify_altar(victim, trap, originator);
			}

			break;

		case SIGN:
			/* Only player should be able read signs */
			if (victim->type == PLAYER)
			{
				apply_sign(victim, trap);
			}

			break;

		case CONTAINER:
			if (victim->type == PLAYER)
			{
				(void) esrv_apply_container(victim, trap);
			}

			break;

		case RUNE:
			if (!(flags & MOVE_APPLY_VANISHED) && trap->level && IS_LIVE(victim))
			{
				spring_trap(trap, victim);
			}

			break;

#if 0
		/* we don't have this atm. */
		case DEEP_SWAMP:
			if (!(flags & MOVE_APPLY_VANISHED))
			{
				walk_on_deep_swamp(trap, victim);
			}

			break;
#endif

		default:
			LOG(llevDebug, "name %s, arch %s, type %d with fly/walk on/off not handled in move_apply()\n", trap->name, trap->arch->name, trap->type);
			break;
	}

	recursion_depth--;
}