Exemplo n.º 1
0
Arquivo: title.c Projeto: Lundex/lima
int set_title(string str)
{
    if ( this_body() != this_object() )
	error("invalid attempt to set a title\n");

    if ( str && strsrch(str, "$N") == -1 )
	error("bad title -- needs to contain $N\n");

    if ( !str )
	title = sprintf("%s the title-less.", capitalize(query_name()));
    else
	title = replace_string(str,"$N", capitalize(query_name()));
    title += "%^RESET%^";
}
Exemplo n.º 2
0
// look up a player name (name->ID) in the database
// if realname!=NULL, it is set to the database representation
// of the name just looked up (use to get propper capitalization).
// returns 0 for unknown, -1 for no player with that name and >0 for ID
int lookup_name(char *name,char *realname)
{
	int n;
	unsigned int ID;
	char *ptr;

	// spaces and punctuation in text keys confuse mysql. sucks.
	for (ptr=name; *ptr; ptr++) {
		if (!isalpha(*ptr)) return -1;
	}

	if (strlen(name)>38) return -1;	
	if (strlen(name)<2) return -1;	

	if (multi) pthread_mutex_lock(&mutex);

	for (n=0; n<MAXLOOK; n++) {
		if (lookup[n].created+TICKS*60*60<ticker) continue;	// dont use entries older than one hour

		if (!strcasecmp(lookup[n].name,name)) break;
	}
	if (n==MAXLOOK) {
		if (multi) pthread_mutex_unlock(&mutex);
		query_name(name);
		return 0;
	}
	
	if (realname) strcpy(realname,lookup[n].name);

	ID=lookup[n].ID;

	if (multi) pthread_mutex_unlock(&mutex);

	return ID;
}
Exemplo n.º 3
0
void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
                                                   struct work_record *work)
{
  struct nmb_name nmbname;

  /* Only do this if we are using a WINS server. */
  if(we_are_a_wins_client() == False)
  {
    if( DEBUGLVL( 10 ) )
    {
      dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
      dbgtext( "Ignoring, as we are not a WINS client.\n" );
    }
    return;
  }

  make_nmb_name(&nmbname,work->work_group,0x1b);

  /* First, query for the WORKGROUP<1b> name from the WINS server. */
  query_name(unicast_subnet, nmbname.name, nmbname.name_type,
             find_domain_master_name_query_success,
             find_domain_master_name_query_fail,
             NULL);

}
Exemplo n.º 4
0
/** Send a query to look up the address for a name.
 * @param[in] query Callback information.
 * @param[in] name Hostname to look up.
 * @param[in] request DNS lookup structure (may be NULL).
 * @param[in] type Preferred request type.
 */
static void
do_query_name(dns_callback_f callback, void *ctx, const char *name,
              struct reslist *request, int type)
{
  char host_name[HOSTLEN + 1];

  ircd_strncpy(host_name, name, HOSTLEN);
  add_local_domain(host_name, HOSTLEN);

  if (request == NULL)
  {
    request       = make_request(callback, ctx);
    DupString(request->name, host_name);
#ifdef IPV6
    if (type != T_A)
      request->state = REQ_AAAA;
    else
#endif
    request->state = REQ_A;
  }

  request->type = type;
  Debug((DEBUG_DNS, "Requesting DNS %s %s as %p", (request->state == REQ_AAAA ? "AAAA" : "A"), host_name, request));
  query_name(host_name, C_IN, type, request);
}
Exemplo n.º 5
0
state_t &
state_t::time_limit(
	duration_t timeout,
	const state_t & state_to_switch )
{
	if( duration_t::zero() == timeout )
		SO_5_THROW_EXCEPTION( rc_invalid_time_limit_for_state,
				"zero can't be used as time limit for state '" +
				query_name() );

	// Old time limit must be dropped if it exists.
	drop_time_limit();
	m_time_limit.reset( new time_limit_t{ timeout, state_to_switch } );

	// If this state is active then new time limit must be activated.
	if( is_active() )
		so_5::details::do_with_rollback_on_exception(
			[&] {
				m_time_limit->set_up_limit_for_agent( *m_target_agent, *this );
			},
			[&] {
				// Time limit must be dropped because it is not activated
				// for the current state.
				drop_time_limit();
			} );

	return *this;
}
Exemplo n.º 6
0
void check_master_browser_exists(time_t t)
{
	static time_t lastrun=0;
	struct subnet_record *subrec;
	const char *workgroup_name = lp_workgroup();

	if (!lastrun)
		lastrun = t;

	if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
		return;

	lastrun = t;

	dump_workgroups(False);

	for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
		struct work_record *work;

		for (work = subrec->workgrouplist; work; work = work->next) {
			if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) {
				/* Do a name query for the local master browser on this net. */
				query_name( subrec, work->work_group, 0x1d,
					check_for_master_browser_success,
					check_for_master_browser_fail,
					NULL);
			}
		}
	}
}
Exemplo n.º 7
0
void collect_all_workgroup_names_from_wins_server(time_t t)
{
	static time_t lastrun = 0;
	struct work_record *work;

	/* Only do this if we are using a WINS server. */
	if(we_are_a_wins_client() == False)
		return;

	/* Check to see if we are a domain master browser on the unicast subnet. */
	if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) {
		if( DEBUGLVL( 0 ) ) {
			dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
			dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
			dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
		}
		return;
	}

	if(!AM_DOMAIN_MASTER_BROWSER(work))
		return;

	if ((lastrun != 0) && (t < lastrun + (15 * 60)))
		return;
     
	lastrun = t;

	/* First, query for the *<1b> name from the WINS server. */
	query_name(unicast_subnet, "*", 0x1b,
		find_all_domain_master_names_query_success,
		find_all_domain_master_names_query_fail,
		NULL);
} 
Exemplo n.º 8
0
/**
 * Returns adjusted damage based on the caster.
 * @param caster Who is casting.
 * @param spell_type Spell ID we're adjusting.
 * @param base_dam Base damage.
 * @return Adjusted damage. */
int SP_level_dam_adjust(object *caster, int spell_type, int base_dam)
{
	float tmp_add;
	int dam_adj, level = SK_level(caster);

	/* Sanity check */
	if (level <= 0 || level > MAXLEVEL)
	{
		LOG(llevBug, "SP_level_dam_adjust(): object %s has invalid level %d\n", query_name(caster, NULL), level);

		if (level <= 0)
		{
			level = 1;
		}
		else
		{
			level = MAXLEVEL;
		}
	}

	/* get a base damage when we don't have one from caller */
	if (base_dam == -1)
	{
		base_dam = spells[spell_type].bdam;
	}

	if ((tmp_add = LEVEL_DAMAGE(level / 3) - 0.75f) < 0)
	{
		tmp_add = 0;
	}

	dam_adj = (sint16) ((float) base_dam * (LEVEL_DAMAGE(level) + tmp_add) * PATH_DMG_MULT(caster, find_spell(spell_type)));

	return dam_adj;
}
Exemplo n.º 9
0
/**
 * Causes an object to explode, eg, a firebullet, poison cloud ball, etc.
 * @param op The object to explode. */
void explode_object(object *op)
{
	tag_t op_tag = op->count;
	object *tmp;
	int type;

	play_sound_map(op->map, op->x, op->y, SOUND_OB_EXPLODE, SOUND_NORMAL);

	if (op->other_arch == NULL)
	{
		LOG(llevBug, "BUG: explode_object(): op %s without other_arch\n", query_name(op, NULL));
		remove_ob(op);
		check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
		return;
	}

	tmp = arch_to_object(op->other_arch);
	type = tmp->stats.sp;

	if (!type)
	{
		type = op->stats.sp;
	}

	copy_owner(tmp, op);
	cast_cone(op, op, 0, spells[type].bdur, type, op->other_arch);
	hit_map(op, 0, 0);

	/* remove the firebullet */
	if (!was_destroyed(op, op_tag))
	{
		remove_ob(op);
		check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
	}
}
Exemplo n.º 10
0
Arquivo: title.c Projeto: Lundex/lima
string query_title()
{
    /* ensure the player has a title. set it if none (yet) */
    if ( !title )
	title = sprintf("%s the title-less", capitalize(query_name()));

    return title;
}
Exemplo n.º 11
0
Arquivo: player.c Projeto: atrinik/dwc
/**
 * Handles object throwing objects of type "DUST".
 * @todo This function needs to be rewritten. Works for area effect
 * spells only now.
 * @param op Object throwing.
 * @param throw_ob What to throw.
 * @param dir Direction to throw into. */
void cast_dust(object *op, object *throw_ob, int dir)
{
	archetype *arch = NULL;

	if (!(spells[throw_ob->stats.sp].flags & SPELL_DESC_DIRECTION))
	{
		LOG(llevBug, "DEBUG: Warning, dust %s is not AE spell!!\n", query_name(throw_ob, NULL));
		return;
	}

	if (spells[throw_ob->stats.sp].archname)
	{
		arch = find_archetype(spells[throw_ob->stats.sp].archname);
	}

	/* Casting POTION 'dusts' is really use_magic_item skill */
	if (op->type == PLAYER && throw_ob->type == POTION && !change_skill(op, SK_USE_MAGIC_ITEM))
	{
		return;
	}

	if (throw_ob->type == POTION && arch != NULL)
	{
		cast_cone(op, throw_ob, dir, 10, throw_ob->stats.sp, arch);
	}
	/* dust_effect */
	else if ((arch = find_archetype("dust_effect")) != NULL)
	{
		cast_cone(op, throw_ob, dir, 1, 0, arch);
	}
	/* Problem occured! */
	else
	{
		LOG(llevBug, "BUG: cast_dust() can't find an archetype to use!\n");
	}

	if (op->type == PLAYER && arch)
	{
		new_draw_info_format(NDI_UNIQUE, op, "You cast %s.", query_name(throw_ob, NULL));
	}

	if (!QUERY_FLAG(throw_ob, FLAG_REMOVED))
	{
		destruct_ob(throw_ob);
	}
}
Exemplo n.º 12
0
int on_drop( object player ) {
   if( !::on_drop(player) ) return 0;
   if( query_held() ) {
      set_held( 0 );
      player->msg_local( "~CACT~Name ~verbtake off ~poss " + query_name() + " and ~verbdrop it.~CDEF" );
      return MOVE_SILENCE_FLAG | MOVE_OK_FLAG;
   }
   else return MOVE_OK_FLAG;
}
Exemplo n.º 13
0
int on_give( object giver, object receiver ) {
   if( !::on_give(giver, receiver) ) return 0;
   if( query_held() ) {
      set_held( 0 );
      giver->msg_local( "~CACT~Name ~verbtake off ~poss " + query_name() + " and ~verbgive it to " + receiver->query_specific() + ".~CDEF" );
      return MOVE_SILENCE_FLAG | MOVE_OK_FLAG;
   }
   else return MOVE_OK_FLAG;
}
Exemplo n.º 14
0
Arquivo: object.c Projeto: atrinik/dwc
/**
 * Check if an item op can be put into a sack. If pl exists then tell
 * a player the reason of failure.
 * @param pl Player object.
 * @param sack The sack.
 * @param op The object to check.
 * @param nrof Number of objects we want to put in.
 * @return 1 if the object will fit, 0 if it will not. */
int sack_can_hold(object *pl, object *sack, object *op, int nrof)
{
	char buf[MAX_BUF];

	buf[0] = '\0';

	if (!QUERY_FLAG(sack, FLAG_APPLIED))
	{
		snprintf(buf, sizeof(buf), "The %s is not active.", query_name(sack, NULL));
	}

	if (sack == op)
	{
		snprintf(buf, sizeof(buf), "You can't put the %s into itself.", query_name(sack, NULL));
	}

	if ((sack->race && (sack->sub_type & 1) != ST1_CONTAINER_CORPSE) && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type)))
	{
		snprintf(buf, sizeof(buf), "You can put only %s into the %s.", sack->race, query_name(sack, NULL));
	}

	if (op->type == KEY && sack->slaying && op->slaying)
	{
		snprintf(buf, sizeof(buf), "You don't want put the key into %s.", query_name(sack, NULL));
	}

	if (sack->weight_limit && sack->carrying + (sint32) ((float) (((nrof ? nrof : 1) * op->weight) + op->carrying) * sack->weapon_speed) > (sint32) sack->weight_limit)
	{
		snprintf(buf, sizeof(buf), "That won't fit in the %s!", query_name(sack, NULL));
	}

	if (buf[0])
	{
		if (pl)
		{
			new_draw_info(NDI_UNIQUE, pl, buf);
		}

		return 0;
	}

	return 1;
}
Exemplo n.º 15
0
/** Send a query to look up the name for an address.
 * @param[in] query Callback information.
 * @param[in] addr Address to look up.
 * @param[in] request DNS lookup structure (may be NULL).
 */
static void
do_query_number(dns_callback_f callback, void *ctx, const struct irc_in_addr *addr,
                struct reslist *request)
{
  char ipbuf[128];
  const unsigned char *cp;

  if (irc_in_addr_is_ipv4(addr))
  {
    cp = (const unsigned char*)&addr->in6_16[6];
    ircd_snprintf(NULL, ipbuf, sizeof(ipbuf), "%u.%u.%u.%u.in-addr.arpa.",
                  (unsigned int)(cp[3]), (unsigned int)(cp[2]),
                  (unsigned int)(cp[1]), (unsigned int)(cp[0]));
  }
  else
  {
    const char *intarpa;

    if (request != NULL && request->state == REQ_INT)
      intarpa = "int";
    else
      intarpa = "arpa";

    cp = (const unsigned char *)&addr->in6_16[0];
    ircd_snprintf(NULL, ipbuf, sizeof(ipbuf),
                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x."
                  "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.%s.",
                  (unsigned int)(cp[15]&0xf), (unsigned int)(cp[15]>>4),
                  (unsigned int)(cp[14]&0xf), (unsigned int)(cp[14]>>4),
                  (unsigned int)(cp[13]&0xf), (unsigned int)(cp[13]>>4),
                  (unsigned int)(cp[12]&0xf), (unsigned int)(cp[12]>>4),
                  (unsigned int)(cp[11]&0xf), (unsigned int)(cp[11]>>4),
                  (unsigned int)(cp[10]&0xf), (unsigned int)(cp[10]>>4),
                  (unsigned int)(cp[9]&0xf), (unsigned int)(cp[9]>>4),
                  (unsigned int)(cp[8]&0xf), (unsigned int)(cp[8]>>4),
                  (unsigned int)(cp[7]&0xf), (unsigned int)(cp[7]>>4),
                  (unsigned int)(cp[6]&0xf), (unsigned int)(cp[6]>>4),
                  (unsigned int)(cp[5]&0xf), (unsigned int)(cp[5]>>4),
                  (unsigned int)(cp[4]&0xf), (unsigned int)(cp[4]>>4),
                  (unsigned int)(cp[3]&0xf), (unsigned int)(cp[3]>>4),
                  (unsigned int)(cp[2]&0xf), (unsigned int)(cp[2]>>4),
                  (unsigned int)(cp[1]&0xf), (unsigned int)(cp[1]>>4),
                  (unsigned int)(cp[0]&0xf), (unsigned int)(cp[0]>>4), intarpa);
  }
  if (request == NULL)
  {
    request       = make_request(callback, ctx);
    request->state= REQ_PTR;
    request->type = T_PTR;
    memcpy(&request->addr, addr, sizeof(request->addr));
    request->name = (char *)MyMalloc(HOSTLEN + 1);
  }
  Debug((DEBUG_DNS, "Requesting DNS PTR %s as %p", ipbuf, request));
  query_name(ipbuf, C_IN, T_PTR, request);
}
Exemplo n.º 16
0
main(int argc, char *argv[]){

	/** Check the number of parameters */
	if (argc < 5) {
		/** Tell the user how to run the program */
		cerr << "Usage: " << argv[0] << " token encrows results num_threads" << endl;
        	return 1;
	}

	mr_init_threading();
	PFC pfc(AES_SECURITY);

	SecureSelect *db=NULL;

	int m=0;
	string query_name(argv[1]);
	string enctable_name(argv[2]);
	string results_name(argv[3]);
	int num_threads = atoi(argv[4]);

	db = new SecureSelect(&pfc,pfc.order());

	if (!ifstream(query_name+"_ptok")){
		cout << "Query file doesn't exist" << endl;
		return 0;
	}

	if (!ifstream(enctable_name+"_enc_msgs")){
		cout << "Enctable file doesn't exist" << endl;
		return 0;
	}

	#ifdef VERBOSE
	int start = getMilliCount();
	#endif
	int res_num = db->ApplyPTokenMT(query_name, enctable_name, results_name, num_threads);
	//int res_num = db->ApplyPToken(query_name, enctable_name, results_name);
	#ifdef VERBOSE
	int milliSecondsElapsed = getMilliSpan(start);
	cout << "\texec time " << milliSecondsElapsed << endl;
	#endif

	if(res_num >=0){
		cout << res_num << " result(s) found" << endl;
		return 1;
	}
	else
		return 0;

}
Exemplo n.º 17
0
Arquivo: apply.c Projeto: atrinik/dwc
/**
 * Attempt to apply the object 'below' the player.
 *
 * If the player has an open container, we use that for below, otherwise
 * we use the ground.
 * @param pl Player. */
void player_apply_below(object *pl)
{
	object *tmp, *next;
	int floors;

	if (pl->type != PLAYER)
	{
		LOG(llevBug, "BUG: player_apply_below() called for non player object >%s<\n", query_name(pl, NULL));
		return;
	}

	tmp = pl->below;

	/* This is perhaps more complicated.  However, I want to make sure that
	 * we don't use a corrupt pointer for the next object, so we get the
	 * next object in the stack before applying.  This is can only be a
	 * problem if player_apply() has a bug in that it uses the object but does
	 * not return a proper value. */
	for (floors = 0; tmp != NULL; tmp = next)
	{
		next = tmp->below;

		if (QUERY_FLAG(tmp, FLAG_IS_FLOOR))
		{
			floors++;
		}
		/* Process only floor objects after first floor object */
		else if (floors > 0)
		{
			return;
		}

		if (!IS_INVISIBLE(tmp, pl) || QUERY_FLAG(tmp, FLAG_WALK_ON) || QUERY_FLAG(tmp, FLAG_FLY_ON))
		{
			if (player_apply(pl, tmp, 0, 1) == 1)
			{
				return;
			}
		}

		/* Process at most two floor objects */
		if (floors >= 2)
		{
			return;
		}
	}
}
Exemplo n.º 18
0
Arquivo: shop.c Projeto: atrinik/dwc
/**
 * Player is selling an item. Give money, print appropriate messages.
 * @param op Object to sell.
 * @param pl Player. Shouldn't be NULL or non player.
 * @param value If op is NULL, this value is used instead of using
 * query_cost(). */
void sell_item(object *op, object *pl, sint64 value)
{
	sint64 i;

	if (pl == NULL || pl->type != PLAYER)
	{
		LOG(llevDebug, "DEBUG: sell_item(): Object other than player tried to sell something.\n");
		return;
	}

	if (op == NULL)
	{
		i = value;
	}
	else
	{
		i = query_cost(op, pl, F_SELL);
	}

	if (!i)
	{
		if (op)
		{
			new_draw_info_format(NDI_UNIQUE, pl, "We're not interested in %s.", query_name(op, NULL));
		}
	}

	i = insert_coins(pl, i);

	if (!op)
	{
		return;
	}

	if (i != 0)
	{
		LOG(llevBug, "BUG: Warning - payment not zero: %d\n", i);
	}

	new_draw_info_format(NDI_UNIQUE, pl, "You receive %s for %s.", query_cost_string(op, pl, 1), query_name(op, NULL));
	SET_FLAG(op, FLAG_UNPAID);

	/* Identify the item. Makes any unidentified item sold to unique shop appear identified. */
	identify(op);
}
Exemplo n.º 19
0
Arquivo: apply.c Projeto: atrinik/dwc
/**
 * Living thing is applying an object.
 * @param pl ::object causing op to be applied.
 * @param op ::object being applied.
 * @param aflag Special (always apply/unapply) flags. Nothing is done
 * with them in this function - they are passed to apply_special().
 * @param quiet If 1, suppresses the "don't know how to apply" and "you
 * must get it first" messages as needed by player_apply_below(). There
 * can still be "but you are floating high above the ground" messages.
 * @retval 0 Player or monster can't apply objects of that type.
 * @retval 1 Has been applied, or there was an error applying the object.
 * @retval 2 Objects of that type can't be applied if not in
 * inventory. */
int player_apply(object *pl, object *op, int aflag, int quiet)
{
	int tmp;

	if (op->env == NULL && QUERY_FLAG(pl, FLAG_FLYING))
	{
		/* Player is flying and applying object not in inventory */
		if (!QUERY_FLAG(pl, FLAG_WIZ) && !QUERY_FLAG(op, FLAG_FLYING) && !QUERY_FLAG(op, FLAG_FLY_ON))
		{
			new_draw_info(NDI_UNIQUE, pl, "But you are floating high above the ground!");
			return 0;
		}
	}

	if (op->type != PLAYER && QUERY_FLAG(op, FLAG_WAS_WIZ) && !QUERY_FLAG(pl, FLAG_WAS_WIZ))
	{
		play_sound_map(pl->map, pl->x, pl->y, SOUND_OB_EVAPORATE, SOUND_NORMAL);
		new_draw_info(NDI_UNIQUE, pl, "The object disappears in a puff of smoke!");
		new_draw_info(NDI_UNIQUE, pl, "It must have been an illusion.");
		remove_ob(op);
		check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
		return 1;
	}

	tmp = manual_apply(pl, op, aflag);

	if (!quiet)
	{
		if (tmp == 0)
		{
			new_draw_info_format(NDI_UNIQUE, pl, "I don't know how to apply the %s.", query_name(op, NULL));
		}
		else if (tmp == 2)
		{
			new_draw_info_format(NDI_UNIQUE, pl, "You must get it first!\n");
		}
	}

	return tmp;
}
Exemplo n.º 20
0
Arquivo: apply.c Projeto: atrinik/dwc
/**
 * Make player forget a spell.
 * @param op Player object to make forget the spell.
 * @param spell ID of the spell. */
void do_forget_spell(object *op, int spell)
{
	object *tmp;
	int i;

	if (op->type != PLAYER)
	{
		LOG(llevBug, "BUG: do_forget_spell(): Not a player: %s (%d).\n", query_name(op, NULL), spell);
		return;
	}

	if (!check_spell_known(op, spell))
	{
		LOG(llevBug, "BUG: do_forget_spell(): Spell %d not known.\n", spell);
		return;
	}

	play_sound_player_only(CONTR(op), SOUND_LOSE_SOME,SOUND_NORMAL,0,0);
	new_draw_info_format(NDI_UNIQUE, op, "You lose knowledge of %s.", spells[spell].name);

	send_spelllist_cmd(op, spells[spell].name, SPLIST_MODE_REMOVE);
	tmp = find_special_prayer_mark(op, spell);

	if (tmp)
	{
		remove_ob(tmp);
	}

	for (i = 0; i < CONTR(op)->nrofknownspells; i++)
	{
		if (CONTR(op)->known_spells[i] == spell)
		{
			CONTR(op)->known_spells[i] = CONTR(op)->known_spells[--CONTR(op)->nrofknownspells];
			return;
		}
	}

	LOG(llevBug, "BUG: do_forget_spell(): Couldn't find spell %d.\n", spell);
}
Exemplo n.º 21
0
const state_t *
state_t::actual_state_to_enter() const
{
	const state_t * s = this;
	while( 0 != s->m_substate_count )
	{
		if( s->m_last_active_substate )
			// Note: for states with shallow history m_last_active_substate
			// can point to composite substate. This substate must be
			// processed usual way with checking for substate count, presence
			// of initial substate and so on...
			s = s->m_last_active_substate;
		else if( !s->m_initial_substate )
			SO_5_THROW_EXCEPTION( rc_no_initial_substate,
					"there is no initial substate for composite state: " +
					query_name() );
		else
			s = s->m_initial_substate;
	}

	return s;
}
Exemplo n.º 22
0
/**
 * Causes cone object 'op' to move a space/hit creatures.
 * @param op Cone object moving. */
void move_cone(object *op)
{
	int i;
	tag_t tag;

	/* If no map then hit_map will crash so just ignore object */
	if (!op->map)
	{
		LOG(llevBug, "BUG: Tried to move_cone object %s without a map.\n", query_name(op, NULL));
		remove_ob(op);
		check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
		return;
	}

	/* Lava saves it's life, but not yours :) */
	if (QUERY_FLAG(op, FLAG_LIFESAVE))
	{
		hit_map(op, 0, 0);
		return;
	}

	/* If no owner left, the spell dies out. */
	if (get_owner(op) == NULL)
	{
		remove_ob(op);
		check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
		return;
	}

	/* Hit map returns 1 if it hits a monster.  If it does, set
	 * food to 1, which will stop the cone from progressing. */
	tag = op->count;
	op->stats.food |= hit_map(op, 0, 1);

	if (was_destroyed(op, tag))
	{
		return;
	}

	if ((op->stats.hp -= 2) < 0)
	{
		if (op->stats.exp)
		{
			op->speed = 0;
			update_ob_speed(op);
			op->stats.exp = 0;
			/* So they will join */
			op->stats.sp = 0;
		}
		else
		{
			remove_ob(op);
			check_walk_off(op, NULL, MOVE_APPLY_VANISHED);
		}

		return;
	}

	if (op->stats.food)
	{
		return;
	}

	op->stats.food = 1;

	for (i = -1; i < 2; i++)
	{
		int x = op->x + freearr_x[absdir(op->stats.sp + i)], y = op->y + freearr_y[absdir(op->stats.sp + i)];

		if (ok_to_put_more(op->map, x, y, op))
		{
			object *tmp = arch_to_object(op->arch);

			copy_owner(tmp, op);

			/* *very* important - this is the count value of the
			 * *first* object we created with this cone spell.
			 * we use it for identify this spell. Miss this
			 * and ok_to_put_more will allow to create 1000th
			 * in a single tile! */
			tmp->weight_limit = op->weight_limit;
			tmp->x = x, tmp->y = y;

			tmp->level = op->level;
			tmp->stats.sp = op->stats.sp, tmp->stats.hp = op->stats.hp + 1;
			tmp->stats.maxhp = op->stats.maxhp;
			tmp->stats.dam = op->stats.dam;

			if (!insert_ob_in_map(tmp, op->map, op, 0))
			{
				return;
			}

			if (tmp->other_arch)
			{
				cone_drop(tmp);
			}
		}
	}
}
Exemplo n.º 23
0
Arquivo: apply.c Projeto: atrinik/dwc
/**
 * Main apply handler.
 *
 * Checks for unpaid items before applying.
 * @param op ::object causing tmp to be applied.
 * @param tmp ::object being applied.
 * @param aflag Special (always apply/unapply) flags. Nothing is done
 * with them in this function - they are passed to apply_special().
 * @retval 0 Player or monster can't apply objects of that type.
 * @retval 1 Has been applied, or there was an error applying the object.
 * @retval 2 Objects of that type can't be applied if not in
 * inventory. */
int manual_apply(object *op, object *tmp, int aflag)
{
	if (tmp->head)
	{
		tmp = tmp->head;
	}

	if (op->type == PLAYER)
	{
		CONTR(op)->praying = 0;
	}

	if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED))
	{
		if (op->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, op, "You should pay for it first.");
			return 1;
		}
		/* Monsters just skip unpaid items */
		else
		{
			return 0;
		}
	}

	/* Monsters must not apply random chests, nor magic_mouths with a counter */
	if (op->type != PLAYER && tmp->type == TREASURE)
	{
		return 0;
	}

	/* Trigger the APPLY event */
	if (!(aflag & AP_NO_EVENT) && trigger_event(EVENT_APPLY, op, tmp, NULL, NULL, aflag, 0, 0, SCRIPT_FIX_ACTIVATOR))
	{
		return 1;
	}

	aflag &= ~AP_NO_EVENT;

	/* Control apply by controling a set exp object level or player exp level */
	if (tmp->item_level)
	{
		int tmp_lev;

		if (tmp->item_skill)
		{
			tmp_lev = find_skill_exp_level(op, tmp->item_skill);
		}
		else
		{
			tmp_lev = op->level;
		}

		if (tmp->item_level > tmp_lev)
		{
			new_draw_info(NDI_UNIQUE, op, "The item level is too high to apply.");
			return 1;
		}
	}

	switch (tmp->type)
	{
		case HOLY_ALTAR:
			new_draw_info_format(NDI_UNIQUE, op, "You touch the %s.", tmp->name);

			if (change_skill(op, SK_PRAYING))
			{
				pray_at_altar(op, tmp);
			}
			else
			{
				new_draw_info(NDI_UNIQUE, op, "Nothing happens. It seems you miss the right skill.");
			}

			return 1;
			break;

		case HANDLE:
			new_draw_info(NDI_UNIQUE, op, "You turn the handle.");
			play_sound_map(op->map, op->x, op->y, SOUND_TURN_HANDLE, SOUND_NORMAL);
			tmp->value = tmp->value ? 0 : 1;
			SET_ANIMATION(tmp, ((NUM_ANIMATIONS(tmp) / NUM_FACINGS(tmp)) * tmp->direction) + tmp->value);
			update_object(tmp, UP_OBJ_FACE);
			push_button(tmp);

			return 1;

		case TRIGGER:
			if (check_trigger(tmp, op))
			{
				new_draw_info(NDI_UNIQUE, op, "You turn the handle.");
				play_sound_map(tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE, SOUND_NORMAL);
			}
			else
			{
				new_draw_info(NDI_UNIQUE, op, "The handle doesn't move.");
			}

			return 1;

		case EXIT:
			if (op->type != PLAYER || !tmp->map)
			{
				return 0;
			}

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

			if (!EXIT_PATH(tmp) || !is_legal_2ways_exit(op, tmp) || (EXIT_Y(tmp) == -1 && EXIT_X(tmp) == -1))
			{
				new_draw_info_format(NDI_UNIQUE, op, "The %s is closed.", query_name(tmp, NULL));
			}
			else
			{
				/* Don't display messages for random maps. */
				if (tmp->msg && strncmp(EXIT_PATH(tmp), "/!", 2) && strncmp(EXIT_PATH(tmp), "/random/", 8))
				{
					new_draw_info(NDI_NAVY, op, tmp->msg);
				}

				enter_exit(op, tmp);
			}

			return 1;

		case SIGN:
			apply_sign(op, tmp);
			return 1;

		case BOOK:
			if (op->type == PLAYER)
			{
				apply_book(op, tmp);
				return 1;
			}

			return 0;

		case SKILLSCROLL:
			if (op->type == PLAYER)
			{
				apply_skillscroll(op, tmp);
				return 1;
			}

			return 0;

		case SPELLBOOK:
			if (op->type == PLAYER)
			{
				apply_spellbook(op, tmp);
				return 1;
			}

			return 0;

		case SCROLL:
			apply_scroll(op, tmp);
			return 1;

		case POTION:
			(void) apply_potion(op, tmp);
			return 1;

		case LIGHT_APPLY:
			apply_player_light(op, tmp);
			return 1;

		case LIGHT_REFILL:
			apply_player_light_refill(op, tmp);
			return 1;

		/* Eneq(@csd.uu.se): Handle apply on containers. */
		case CLOSE_CON:
			if (op->type == PLAYER)
			{
				(void) esrv_apply_container(op, tmp->env);
			}

			return 1;

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

			return 1;

		case TREASURE:
			apply_treasure(op, tmp);
			return 1;

		case WEAPON:
		case ARMOUR:
		case BOOTS:
		case GLOVES:
		case AMULET:
		case GIRDLE:
		case BRACERS:
		case SHIELD:
		case HELMET:
		case RING:
		case CLOAK:
		case WAND:
		case ROD:
		case HORN:
		case SKILL:
		case BOW:
		case SKILL_ITEM:
			/* Not in inventory */
			if (tmp->env != op)
			{
				return 2;
			}

			(void) apply_special(op, tmp, aflag);
			return 1;

		case DRINK:
		case FOOD:
		case FLESH:
			apply_food(op, tmp);
			return 1;

		case POISON:
			apply_poison(op, tmp);
			return 1;

		case SAVEBED:
			if (op->type == PLAYER)
			{
				apply_savebed(op);
				return 1;
			}

			return 0;

		case ARMOUR_IMPROVER:
			if (op->type == PLAYER)
			{
				apply_armour_improver(op, tmp);
				return 1;
			}

			return 0;

		case WEAPON_IMPROVER:
			apply_weapon_improver(op, tmp);
			return 1;

		case CLOCK:
			if (op->type == PLAYER)
			{
				timeofday_t tod;

				get_tod(&tod);
				new_draw_info_format(NDI_UNIQUE, op, "It is %d minute%s past %d o'clock %s", tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), ((tod.hour % (HOURS_PER_DAY / 2) == 0) ? (HOURS_PER_DAY / 2) : ((tod.hour) % (HOURS_PER_DAY / 2))), ((tod.hour >= (HOURS_PER_DAY / 2)) ? "pm" : "am"));
				return 1;
			}

			return 0;

		case POWER_CRYSTAL:
			apply_power_crystal(op, tmp);
			return 1;

		/* For lighting torches/lanterns/etc */
		case LIGHTER:
			if (op->type == PLAYER)
			{
				apply_lighter(op, tmp);
				return 1;
			}

			return 0;

		/* So the below default case doesn't execute for these objects,
		 * even if they have message. */
		case DOOR:
			return 0;

		/* Nothing from the above... but show a message if it has one. */
		default:
			if (tmp->msg)
			{
				new_draw_info(NDI_UNIQUE, op, tmp->msg);
				return 1;
			}

			return 0;
	}
}
Exemplo n.º 24
0
Arquivo: shop.c Projeto: atrinik/dwc
/**
 * Descends containers looking for unpaid items, and pays for them.
 * @param pl Player buying the stuff.
 * @param op Object we are examining. If op has and inventory, we examine
 * that. Ii there are objects below op, we descend down.
 * @retval 0 Player still has unpaid items.
 * @retval 1 Player has paid for everything. */
int get_payment(object *pl, object *op)
{
	char buf[MAX_BUF];
	int ret = 1;

	if (op != NULL && op->inv)
	{
		ret = get_payment(pl, op->inv);
	}

	if (!ret)
	{
		return 0;
	}

	if (op != NULL && op->below)
	{
		ret = get_payment(pl, op->below);
	}

	if (!ret)
	{
		return 0;
	}

	if (op != NULL && QUERY_FLAG(op, FLAG_UNPAID))
	{
		strncpy(buf, query_cost_string(op, pl, F_BUY), sizeof(buf));

		if (!pay_for_item(op, pl))
		{
			sint64 i = query_cost(op, pl, F_BUY) - query_money(pl);

			CLEAR_FLAG(op, FLAG_UNPAID);
			new_draw_info_format(NDI_UNIQUE, pl, "You lack %s to buy %s.", cost_string_from_value(i), query_name(op, NULL));
			SET_FLAG(op, FLAG_UNPAID);
			return 0;
		}
		else
		{
			object *tmp, *c_cont = op->env;
			tag_t c = op->count;

			CLEAR_FLAG(op, FLAG_UNPAID);
			CLEAR_FLAG(op, FLAG_STARTEQUIP);

			if (pl->type == PLAYER)
			{
				new_draw_info_format(NDI_UNIQUE, pl, "You paid %s for %s.", buf, query_name(op, NULL));
			}

			tmp = merge_ob(op, NULL);

			if (pl->type == PLAYER)
			{
				/* It was merged */
				if (tmp)
				{
					esrv_del_item(CONTR(pl), c, c_cont);
					op = tmp;
				}

				esrv_send_item(pl, op);
			}
		}
	}

	return 1;
}
Exemplo n.º 25
0
/**
 * Remove a player from the game that has been disconnected by logging
 * out, the socket connection was interrupted, etc.
 * @param pl The player to remove. */
void remove_ns_dead_player(player *pl)
{
	if (pl == NULL || pl->ob->type == DEAD_OBJECT)
	{
		return;
	}

	if (pl->state == ST_PLAYING)
	{
		/* Trigger the global LOGOUT event */
		trigger_global_event(GEVENT_LOGOUT, pl->ob, pl->socket.host);

		if (!pl->dm_stealth)
		{
			new_draw_info_format(NDI_UNIQUE | NDI_ALL | NDI_DK_ORANGE, NULL, "%s left the game.", query_name(pl->ob, NULL));
		}

		/* If this player is in a party, leave the party */
		if (pl->party)
		{
			command_party(pl->ob, "leave");
		}

		strncpy(pl->killer, "left", MAX_BUF - 1);
		hiscore_check(pl->ob, 1);

		/* Be sure we have closed container when we leave */
		container_unlink(pl, NULL);

		save_player(pl->ob, 0);

		if (!QUERY_FLAG(pl->ob, FLAG_REMOVED))
		{
			leave_map(pl->ob);
		}

		if (pl->ob->map)
		{
			if (pl->ob->map->in_memory == MAP_IN_MEMORY)
			{
				pl->ob->map->timeout = MAP_TIMEOUT(pl->ob->map);
			}

			pl->ob->map = NULL;
		}
	}

	LOG(llevInfo, "LOGOUT: >%s< from IP %s\n", pl->ob->name, pl->socket.host);

	/* To avoid problems with inventory window */
	pl->ob->type = DEAD_OBJECT;
	free_player(pl);
}
Exemplo n.º 26
0
Arquivo: shop.c Projeto: atrinik/dwc
/**
 * This pays for the item, and takes the proper amount of money off the
 * player.
 * @param op Player paying.
 * @param pouch Container (pouch or player) to remove the coins from.
 * @param to_pay Required amount.
 * @return Amount still not paid after using "pouch". */
static sint64 pay_from_container(object *op, object *pouch, sint64 to_pay)
{
	sint64 remain;
	int count, i;
	object *tmp, *coin_objs[NUM_COINS], *next, *bank_object = NULL;
	archetype *at;
	object *who;

	(void) op;

	if (pouch->type != PLAYER && pouch->type != CONTAINER)
	{
		return to_pay;
	}

	remain = to_pay;

	for (i = 0; i < NUM_COINS; i++)
	{
		coin_objs[i] = NULL;
	}

	/* This hunk should remove all the money objects from the player/container */
	for (tmp = pouch->inv; tmp; tmp = next)
	{
		next = tmp->below;

		if (tmp->type == MONEY)
		{
			for (i = 0; i < NUM_COINS; i++)
			{
				if (!strcmp(coins[NUM_COINS - 1 - i], tmp->arch->name) && (tmp->value == tmp->arch->clone.value))
				{
					/* This should not happen, but if it does, just merge
					 * the two. */
					if (coin_objs[i] != NULL)
					{
						LOG(llevBug, "BUG: pay_from_container(): %s has two money entries of (%s)\n", query_name(pouch, NULL), coins[NUM_COINS - 1 - i]);
						remove_ob(tmp);
						coin_objs[i]->nrof += tmp->nrof;
						esrv_del_item(CONTR(pouch), tmp->count, tmp->env);
					}
					else
					{
						remove_ob(tmp);

						if (pouch->type == PLAYER)
						{
							esrv_del_item(CONTR(pouch), tmp->count,tmp->env);
						}

						coin_objs[i] = tmp;
					}

					break;
				}
			}

			if (i == NUM_COINS)
			{
				LOG(llevBug, "BUG: pay_from_container(): Did not find string match for %s\n", tmp->arch->name);
			}
		}
		else if (tmp->arch->name == shstr_cons.player_info && tmp->name == shstr_cons.BANK_GENERAL)
		{
			bank_object = tmp;
		}
	}

	/* Fill in any gaps in the coin_objs array - needed to make change. */
	/* Note that the coin_objs array goes from least value to greatest value */
	for (i = 0; i < NUM_COINS; i++)
	{
		if (coin_objs[i] == NULL)
		{
			at = find_archetype(coins[NUM_COINS - 1 - i]);

			if (at == NULL)
			{
				LOG(llevBug, "BUG: pay_from_container(): Could not find %s archetype", coins[NUM_COINS - 1 - i]);
			}

			coin_objs[i] = get_object();
			copy_object(&at->clone, coin_objs[i], 0);
			coin_objs[i]->nrof = 0;
		}
	}

	for (i = 0; i < NUM_COINS; i++)
	{
		sint64 num_coins;

		if ((sint64) (coin_objs[i]->nrof * coin_objs[i]->value) > remain)
		{
			num_coins = remain / coin_objs[i]->value;

			if ((num_coins * coin_objs[i]->value) < remain)
			{
				num_coins++;
			}
		}
		else
		{
			num_coins = coin_objs[i]->nrof;
		}

		if (num_coins > ((sint64) 1 << 31))
		{
			LOG(llevDebug, "DEBUG: pay_from_container(): Money overflow value->nrof: number of coins > 2 ^ 32 (type coin %d)\n", i);
			num_coins = ((sint64) 1 << 31);
		}

		remain -= num_coins * coin_objs[i]->value;
		coin_objs[i]->nrof -= (uint32) num_coins;
		/* Now start making change.  Start at the coin value
		 * below the one we just did, and work down to
		 * the lowest value. */
		count = i - 1;

		while (remain < 0 && count >= 0)
		{
			num_coins = -remain / coin_objs[count]->value;
			coin_objs[count]->nrof += (uint32) num_coins;
			remain += num_coins * coin_objs[count]->value;
			count--;
		}
	}

	/* If there's still some remain, that means we could try to pay from
	 * bank. */
	if (bank_object && bank_object->value != 0 && remain != 0 && bank_object->value >= remain)
	{
		bank_object->value -= remain;
		remain = 0;
	}

	for (i = 0; i < NUM_COINS; i++)
	{
		if (coin_objs[i]->nrof)
		{
			object *tmp = insert_ob_in_ob(coin_objs[i], pouch);

			for (who = pouch; who && who->type != PLAYER && who->env != NULL; who = who->env)
			{
			}

			esrv_send_item(who, tmp);
			esrv_send_item (who, pouch);
			esrv_update_item(UPD_WEIGHT, who, pouch);

			if (pouch->type != PLAYER)
			{
				esrv_send_item(who, who);
				esrv_update_item(UPD_WEIGHT, who, who);
			}
		}
	}

	return remain;
}
Exemplo n.º 27
0
Arquivo: shop.c Projeto: atrinik/dwc
/**
 * Return the price of an item for a character.
 * @param tmp Object we're querying the price of.
 * @param who Who is inquiring. Can be NULL, only meaningful if player.
 * @param flag Combination of @ref F_xxx "F_xxx" flags.
 * @return The price for the item. */
sint64 query_cost(object *tmp, object *who, int flag)
{
	sint64 val;
	double diff;
	int number;
	int charisma = 11;

	if ((number = tmp->nrof) == 0)
	{
		number = 1;
	}

	/* Money is always identified */
	if (tmp->type == MONEY)
	{
		return (number * tmp->value);
	}

	/* Handle identified items */
	if (QUERY_FLAG(tmp, FLAG_IDENTIFIED) || !need_identify(tmp))
	{
		if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))
		{
			return 0;
		}
		else
		{
			val = tmp->value * number;
		}
	}
	/* This area deals with objects that are not identified, but can be */
	else
	{
		if (tmp->arch != NULL)
		{
			if (flag == F_BUY)
			{
				LOG(llevBug, "BUG: query_cost(): Asking for buy-value of unidentified object %s.\n", query_name(tmp, NULL));
				val = tmp->arch->clone.value * number;
			}
			/* Trying to sell something, or get true value */
			else
			{
				/* Selling unidentified gems is *always* stupid */
				if (tmp->type == GEM || tmp->type == JEWEL || tmp->type == NUGGET || tmp->type == PEARL)
				{
					val = number * 3;
				}
				/* Don't want to give anything away */
				else if (tmp->type == POTION)
				{
					val = number * 50;
				}
				else
				{
					val = number * tmp->arch->clone.value;
				}
			}
		}
		else
		{
			/* No archetype with this object - we generate some dummy values to avoid server break */
			LOG(llevBug, "BUG: query_cost(): Have object with no archetype: %s\n", query_name(tmp, NULL));

			if (flag == F_BUY)
			{
				LOG(llevBug, "BUG: query_cost(): Asking for buy-value of unidentified object without arch.\n");
				val = number * 100;
			}
			else
			{
				val = number * 80;
			}
		}
	}

	/* Wands will count special. The base value is for a wand with one charge */
	if (tmp->type == WAND)
	{
		val += (val * tmp->level) * tmp->stats.food;
	}
	else if (tmp->type == ROD || tmp->type == HORN || tmp->type == POTION || tmp->type == SCROLL)
	{
		val += val * tmp->level;
	}

	/* We are done if we only want get the real value */
	if (flag == F_TRUE)
	{
		return val;
	}

	/* First, we adjust charisma for players and count skills in */
	if (who != NULL && who->type == PLAYER)
	{
		/* Used for SK_BARGAINING modification */
		charisma = who->stats.Cha;

		/* This skill will give us a charisma boost */
		if (find_skill(who, SK_BARGAINING))
		{
			charisma += 4;

			if (charisma > MAX_STAT)
			{
				charisma = MAX_STAT;
			}
		}
	}

	/* Now adjust for sell or buy multiplier */
	if (flag == F_BUY)
	{
		diff = (double) (1.0 - (double) cha_bonus[charisma]);
	}
	else
	{
		diff = (double) (0.20 + (double) cha_bonus[charisma]);
	}

	val = (val * (long) (1000 * (diff))) / 1000;

	/* We want to give at least 1 copper for items which have any
	 * value. */
	if (val < 1 && tmp->value > 0)
	{
		val = 1;
	}

	return val;
}
Exemplo n.º 28
0
/**
 * Op throws any object toss_item.
 * @param op Living thing throwing something.
 * @param toss_item Item thrown.
 * @param dir Direction to throw. */
void do_throw(object *op, object *toss_item, int dir)
{
	object *left_cont, *throw_ob = toss_item, *left = NULL, *tmp_op;
	tag_t left_tag;
	rv_vector range_vector;

	if (!throw_ob)
	{
		if (op->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, op, "You have nothing to throw.");
		}

		return;
	}

	if (QUERY_FLAG(throw_ob, FLAG_STARTEQUIP))
	{
		if (op->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, op, "The gods won't let you throw that.");
		}

		return;
	}

	if (throw_ob->weight <= 0)
	{
		new_draw_info_format(NDI_UNIQUE, op, "You can't throw %s.\n", query_base_name(throw_ob, NULL));
		return;
	}

	/* These are throwing objects left to the player */
	left = throw_ob;
	left_cont = left->env;
	left_tag = left->count;

	/* Sometimes get_split_ob can't split an object (because op->nrof==0?)
	 * and returns NULL. We must use 'left' then */
	if ((throw_ob = get_split_ob(throw_ob, 1, NULL, 0)) == NULL)
	{
		throw_ob = left;
		remove_ob(left);
		check_walk_off(left, NULL, MOVE_APPLY_VANISHED);

		if (op->type == PLAYER)
		{
			esrv_del_item(CONTR(op), left->count, left->env);
		}
	}
	else if (op->type == PLAYER)
	{
		if (was_destroyed(left, left_tag))
		{
			esrv_del_item(CONTR(op), left_tag, left_cont);
		}
		else
		{
			esrv_update_item(UPD_NROF, op, left);
		}
	}

	/* Special case: throwing powdery substances like dust, dirt */
	if (QUERY_FLAG(throw_ob, FLAG_DUST))
	{
		cast_dust(op, throw_ob, dir);

		/* update the shooting speed for the player action timer.
		 * We init the used skill with it - its not calculated here.
		 * cast_dust() can change the used skill... */
		if (op->type == PLAYER)
		{
			op->chosen_skill->stats.maxsp = throw_ob->last_grace;
		}

		return;
	}

	/* Targetting throwing */
	if (!dir && op->type == PLAYER && OBJECT_VALID(CONTR(op)->target_object, CONTR(op)->target_object_count))
	{
		dir = get_dir_to_target(op, CONTR(op)->target_object, &range_vector);
	}

	/* Three things here prevent a throw, you aimed at your feet, you
	 * have no effective throwing strength, or you threw at a wall */
	if (!dir || wall(op->map, op->x + freearr_x[dir], op->y + freearr_y[dir]))
	{
		/* Bounces off 'wall', and drops to feet */
		if (!QUERY_FLAG(throw_ob, FLAG_REMOVED))
		{
			remove_ob(throw_ob);

			if (check_walk_off(throw_ob, NULL, MOVE_APPLY_MOVE) != CHECK_WALK_OK)
			{
				return;
			}
		}

		throw_ob->x = op->x;
		throw_ob->y = op->y;

		if (!insert_ob_in_map(throw_ob, op->map, op, 0))
		{
			return;
		}

		if (op->type == PLAYER)
		{
			if (!dir)
			{
				new_draw_info_format(NDI_UNIQUE, op, "You drop %s at the ground.", query_name(throw_ob, NULL));
			}
			else
			{
				new_draw_info(NDI_UNIQUE, op, "Something is in the way.");
			}
		}

		return;
	}

	set_owner(throw_ob, op);
	set_owner(throw_ob->inv, op);
	throw_ob->direction = dir;
	throw_ob->x = op->x;
	throw_ob->y = op->y;

	/* Save original wc and dam */
	throw_ob->last_heal = throw_ob->stats.wc;
	throw_ob->stats.hp = throw_ob->stats.dam;

	/* Speed */
	throw_ob->speed = MIN(1.0f, (speed_bonus[op->stats.Str] + 1.0f) / 1.5f);

	/* Now we get the wc from the used skill. */
	if ((tmp_op = SK_skill(op)))
	{
		throw_ob->stats.wc += tmp_op->last_heal;
	}
	/* Monsters */
	else
	{
		throw_ob->stats.wc += 10;
	}

	throw_ob->stats.wc_range = op->stats.wc_range;

	if (QUERY_FLAG(throw_ob, FLAG_IS_THROWN))
	{
		throw_ob->stats.dam += throw_ob->magic;
		throw_ob->stats.wc += throw_ob->magic;

		/* Adjust for players */
		if (op->type == PLAYER)
		{
			op->chosen_skill->stats.maxsp = throw_ob->last_grace;
			throw_ob->stats.dam = FABS((int) ((float) (throw_ob->stats.dam + dam_bonus[op->stats.Str] / 2) * LEVEL_DAMAGE(SK_level(op))));
			throw_ob->stats.wc += thaco_bonus[op->stats.Dex] + SK_level(op);
		}
		else
		{
			throw_ob->stats.dam = FABS((int) ((float) (throw_ob->stats.dam) * LEVEL_DAMAGE(op->level)));
			throw_ob->stats.wc += 10 + op->level;
		}

		throw_ob->stats.grace = throw_ob->last_sp;
		throw_ob->stats.maxgrace = 60 + (RANDOM() % 12);

		/* Only throw objects get directional faces */
		if (GET_ANIM_ID(throw_ob) && NUM_ANIMATIONS(throw_ob))
		{
			SET_ANIMATION(throw_ob, (NUM_ANIMATIONS(throw_ob) / NUM_FACINGS(throw_ob)) * dir);
		}

		/* Adjust damage with item condition */
		throw_ob->stats.dam = (sint16) (((float) throw_ob->stats.dam / 100.0f) * (float) throw_ob->item_condition);
	}

	if (throw_ob->stats.dam < 0)
	{
		throw_ob->stats.dam = 0;
	}

	update_ob_speed(throw_ob);
	throw_ob->speed_left = 0;

	SET_MULTI_FLAG(throw_ob, FLAG_FLYING);
	SET_FLAG(throw_ob, FLAG_FLY_ON);
	SET_FLAG(throw_ob, FLAG_WALK_ON);

	play_sound_map(op->map, CMD_SOUND_EFFECT, "throw.ogg", op->x, op->y, 0, 0);

	/* Trigger the THROW event */
	trigger_event(EVENT_THROW, op, throw_ob, NULL, NULL, 0, 0, 0, SCRIPT_FIX_ACTIVATOR);

	if (insert_ob_in_map(throw_ob, op->map, op, 0))
	{
		move_arrow(throw_ob);
	}
}
Exemplo n.º 29
0
/**
 * Requests an object to throw by tag reported by the client.
 *
 * We search for it in the inventory of the owner (you've got to be
 * carrying something in order to throw it).
 *
 * Also checks to see if the object is throwable (ie, not applied, cursed
 * worn, etc).
 * @param op Object to search in.
 * @param tag Tag of the object we're looking for.
 * @return The found object or NULL. */
object *find_throw_tag(object *op, tag_t tag)
{
	object *tmp;

	/* Look through the inventory. */
	for (tmp = op->inv; tmp; tmp = tmp->below)
	{
		/* Can't toss invisible or inv-locked items */
		if (IS_SYS_INVISIBLE(tmp) || QUERY_FLAG(tmp, FLAG_INV_LOCKED))
		{
			continue;
		}

		if (tmp->count == tag)
		{
			break;
		}
	}

	if (!tmp)
	{
		return NULL;
	}

	if (QUERY_FLAG(tmp, FLAG_APPLIED))
	{
		/* We can't apply throwing stuff like darts, so this must be a
		 * weapon. Skip if not OR when it can't be thrown OR when it is
		 * startequip which can't be dropped. */
		if (tmp->type != WEAPON || !QUERY_FLAG(tmp, FLAG_IS_THROWN))
		{
			new_draw_info_format(NDI_UNIQUE, op, "You can't throw %s.", query_base_name(tmp, NULL));
			return NULL;
		}
		else if (QUERY_FLAG(tmp, FLAG_STARTEQUIP))
		{
			new_draw_info(NDI_UNIQUE, op, "You can't throw god-given item!");
			return NULL;
		}
		/* If cursed or damned, we can't unapply it - no throwing. */
		else if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED))
		{
			new_draw_info_format(NDI_UNIQUE, op, "The %s sticks to your hand!", query_base_name(tmp, NULL));
			return NULL;
		}
		/* It's a throw hybrid weapon - unapply it. Then we will fire it
		 * after this function returns. */
		else
		{
			if (apply_special(op, tmp, AP_UNAPPLY | AP_NO_MERGE))
			{
				LOG(llevBug, "BUG: find_throw_ob(): couldn't unapply throwing item %s from %s\n", query_name(tmp, NULL), query_name(op, NULL));
				return NULL;
			}
		}
	}
	else
	{
		/* Not weapon nor throwable - no throwing. */
		if ((tmp->type != WEAPON && tmp->type != POTION) && !QUERY_FLAG(tmp, FLAG_IS_THROWN))
		{
			new_draw_info_format(NDI_UNIQUE, op, "You can't throw %s.", query_base_name(tmp, NULL));
			return NULL;
		}
		/* Special message for throw hybrid weapons. */
		else if (tmp->type == WEAPON)
		{
			new_draw_info_format(NDI_UNIQUE, op, "You must apply the %s first.", query_base_name(tmp, NULL));
			return NULL;
		}
	}

	return tmp;
}
Exemplo n.º 30
0
Arquivo: apply.c Projeto: atrinik/dwc
/**
 * Apply an object.
 *
 * This function doesn't check for unpaid items, but checks other
 * restrictions.
 *
 * Usage example:  apply_special(who, op, AP_UNAPPLY | AP_IGNORE_CURSE)
 * @param who Object using op. It can be a monster.
 * @param op Object being used. Should be an equipment type item, eg, one
 * which you put on and keep on for a while, and not something like a
 * potion or scroll.
 * @param aflags Flags.
 * @return 1 if the action could not be completed, 0 on success. */
int apply_special(object *who, object *op, int aflags)
{
	int basic_flag = aflags & AP_BASIC_FLAGS;
	int tmp_flag = 0, i;
	object *tmp;
	char buf[HUGE_BUF];

	if (who == NULL)
	{
		LOG(llevBug, "BUG: apply_special() from object without environment.\n");
		return 1;
	}

	/* op is not in inventory */
	if (op->env != who)
	{
		return 1;
	}

	/* Needs to be initialized */
	buf[0] = '\0';

	if (!QUERY_FLAG(op, FLAG_APPLIED))
	{
		if (!apply_check_item_power(who, op))
		{
			return 1;
		}
	}
	else
	{
		/* Always apply, so no reason to unapply */
		if (basic_flag == AP_APPLY)
		{
			return 0;
		}

		if (!(aflags & AP_IGNORE_CURSE) && (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED)))
		{
			new_draw_info_format(NDI_UNIQUE, who, "No matter how hard you try, you just can't remove it!");
			return 1;
		}

		if (QUERY_FLAG(op, FLAG_PERM_CURSED))
		{
			SET_FLAG(op, FLAG_CURSED);
		}

		if (QUERY_FLAG(op, FLAG_PERM_DAMNED))
		{
			SET_FLAG(op, FLAG_DAMNED);
		}

		CLEAR_FLAG(op, FLAG_APPLIED);

		switch (op->type)
		{
			case WEAPON:
				(void) change_abil(who, op);
				CLEAR_FLAG(who, FLAG_READY_WEAPON);
				snprintf(buf, sizeof(buf), "You unwield %s.", query_name(op, NULL));
				break;

			/* Allows objects to impart skills */
			case SKILL:
				if (op != who->chosen_skill)
				{
					LOG(llevBug, "BUG: apply_special(): applied skill is not chosen skill\n");
				}

				if (who->type == PLAYER)
				{
					CONTR(who)->shoottype = range_none;

					if (!IS_INVISIBLE(op, who))
					{
						/* It's a tool, need to unlink it */
						unlink_skill(op);
						new_draw_info_format(NDI_UNIQUE, who, "You stop using the %s.", query_name(op, NULL));
						new_draw_info_format(NDI_UNIQUE, who, "You can no longer use the skill: %s.", skills[op->stats.sp].name);
					}
				}

				(void) change_abil(who, op);
				who->chosen_skill = NULL;
				buf[0] = '\0';
				break;

			case ARMOUR:
			case HELMET:
			case SHIELD:
			case RING:
			case BOOTS:
			case GLOVES:
			case AMULET:
			case GIRDLE:
			case BRACERS:
			case CLOAK:
				change_abil(who, op);
				snprintf(buf, sizeof(buf), "You unwear %s.", query_name(op, NULL));
				break;

			case BOW:
			case WAND:
			case ROD:
			case HORN:
				snprintf(buf, sizeof(buf), "You unready %s.", query_name(op, NULL));

				if (who->type == PLAYER)
				{
					CONTR(who)->shoottype = range_none;
				}

				break;

			default:
				snprintf(buf, sizeof(buf), "You unapply %s.", query_name(op, NULL));
				break;
		}

		if (buf[0] != '\0' && who->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, who, buf);
		}

		fix_player(who);

		if (!(aflags & AP_NO_MERGE))
		{
			tag_t del_tag = op->count;
			object *cont = op->env;
			tmp = merge_ob(op, NULL);

			if (who->type == PLAYER)
			{
				/* It was merged */
				if (tmp)
				{
					esrv_del_item(CONTR(who), del_tag, cont);
					op = tmp;
				}

				esrv_send_item (who, op);
			}
		}

		return 0;
	}

	if (basic_flag == AP_UNAPPLY)
	{
		return 0;
	}

	i = 0;

	if (op->type == WAND || op->type == ROD || op->type == HORN)
	{
		tmp_flag = 1;
	}

	/* This goes through and checks to see if the player already has
	 * something of that type applied - if so, unapply it. */
	for (tmp = who->inv; tmp != NULL; tmp = tmp->below)
	{
		if ((tmp->type == op->type || (tmp_flag && (tmp->type == WAND || tmp->type == ROD || tmp->type == HORN))) && QUERY_FLAG(tmp, FLAG_APPLIED) && tmp != op)
		{
			if (tmp->type == RING && !i)
			{
				i = 1;
			}
			else if (apply_special(who, tmp, 0))
			{
				return 1;
			}
		}
	}

	if (op->nrof > 1)
	{
		tmp = get_split_ob(op, op->nrof - 1, NULL, 0);
	}
	else
	{
		tmp = NULL;
	}

	switch (op->type)
	{
		case WEAPON:
		{
			if (!QUERY_FLAG(who, FLAG_USE_WEAPON))
			{
				new_draw_info_format(NDI_UNIQUE, who, "You can't use %s.", query_name(op, NULL));

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

			if (!check_weapon_power(who, op->last_eat))
			{
				new_draw_info(NDI_UNIQUE, who, "That weapon is too powerful for you to use.\nIt would consume your soul!");

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

			if (op->level && (strncmp(op->name, who->name, strlen(who->name))))
			{
				/* If the weapon does not have the name as the character,
				 * can't use it (Ragnarok's sword attempted to be used by
				 * Foo: won't work). */
				new_draw_info(NDI_UNIQUE, who, "The weapon does not recognize you as its owner.");

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

			/* If we have applied a shield, don't allow applying of polearm or two-handed weapons */
			if ((op->sub_type >= WEAP_POLE_IMPACT || op->sub_type >= WEAP_2H_IMPACT) && who->type == PLAYER && CONTR(who) && CONTR(who)->equipment[PLAYER_EQUIP_SHIELD])
			{
				new_draw_info(NDI_UNIQUE, who, "You can't wield this weapon and a shield.");

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

			if (!check_skill_to_apply(who, op))
			{
				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp,who);
				}

				return 1;
			}

			SET_FLAG(op, FLAG_APPLIED);
			SET_FLAG(who, FLAG_READY_WEAPON);
			(void) change_abil(who, op);
			snprintf(buf, sizeof(buf), "You wield %s.", query_name(op, NULL));
			break;
		}

		case SHIELD:
			/* Don't allow polearm or two-handed weapons with a shield */
			if ((who->type == PLAYER && CONTR(who) && CONTR(who)->equipment[PLAYER_EQUIP_WEAPON]) && (CONTR(who)->equipment[PLAYER_EQUIP_WEAPON]->sub_type >= WEAP_POLE_IMPACT || CONTR(who)->equipment[PLAYER_EQUIP_WEAPON]->sub_type >= WEAP_2H_IMPACT))
			{
				new_draw_info(NDI_UNIQUE, who, "You can't use a shield with your current weapon.");

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

		case ARMOUR:
		case HELMET:
		case BOOTS:
		case GLOVES:
		case GIRDLE:
		case BRACERS:
		case CLOAK:
			if (!QUERY_FLAG(who, FLAG_USE_ARMOUR))
			{
				new_draw_info_format(NDI_UNIQUE, who, "You can't use %s.", query_name(op, NULL));

				if (tmp != NULL)
				{
					(void) insert_ob_in_ob(tmp, who);
				}

				return 1;
			}

		case RING:
		case AMULET:
			SET_FLAG(op, FLAG_APPLIED);
			(void) change_abil(who, op);
			snprintf(buf, sizeof(buf), "You wear %s.", query_name(op, NULL));
			break;

		/* This part is needed for skill-tools */
		case SKILL:
			if (who->chosen_skill)
			{
				LOG(llevBug, "BUG: apply_special(): can't apply two skills\n");
				return 1;
			}

			if (who->type == PLAYER)
			{
				CONTR(who)->shoottype = range_skill;

				if (!IS_INVISIBLE(op, who))
				{
					/* for tools */
					if (op->exp_obj)
					{
						LOG(llevBug, "BUG: apply_special(SKILL): found unapplied tool with experience object\n");
					}
					else
					{
						(void) link_player_skill(who, op);
					}

					new_draw_info_format(NDI_UNIQUE, who, "You ready %s.", query_name(op, NULL));
					new_draw_info_format(NDI_UNIQUE, who, "You can now use the skill: %s.", skills[op->stats.sp].name);
				}
				else
				{
					send_ready_skill(who, skills[op->stats.sp].name);
				}
			}

			SET_FLAG(op, FLAG_APPLIED);
			(void) change_abil(who, op);
			who->chosen_skill = op;
			buf[0] = '\0';
			break;

		case WAND:
		case ROD:
		case HORN:
		case BOW:
			if (!check_skill_to_apply(who, op))
			{
				return 1;
			}

			SET_FLAG(op, FLAG_APPLIED);
			new_draw_info_format(NDI_UNIQUE, who, "You ready %s.", query_name(op, NULL));

			if (who->type == PLAYER)
			{
				if (op->type == BOW)
				{
					new_draw_info_format(NDI_UNIQUE, who, "You will now fire %s with %s.", op->race ? op->race : "nothing", query_name(op, NULL));
				}
				else
				{
					CONTR(who)->known_spell = (QUERY_FLAG(op, FLAG_BEEN_APPLIED) || QUERY_FLAG(op, FLAG_IDENTIFIED));
				}
			}

			break;

		default:
			snprintf(buf, sizeof(buf), "You apply %s.", query_name(op, NULL));
	}

	if (!QUERY_FLAG(op, FLAG_APPLIED))
	{
		SET_FLAG(op, FLAG_APPLIED);
	}

	if (buf[0] != '\0')
	{
		new_draw_info(NDI_UNIQUE, who, buf);
	}

	if (tmp != NULL)
	{
		tmp = insert_ob_in_ob(tmp, who);
	}

	fix_player(who);

	if (op->type != WAND && who->type == PLAYER)
	{
		SET_FLAG(op, FLAG_BEEN_APPLIED);
	}

	if (QUERY_FLAG(op, FLAG_PERM_CURSED))
	{
		SET_FLAG(op, FLAG_CURSED);
	}

	if (QUERY_FLAG(op, FLAG_PERM_DAMNED))
	{
		SET_FLAG(op, FLAG_DAMNED);
	}

	if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
	{
		if (who->type == PLAYER)
		{
			new_draw_info(NDI_UNIQUE, who, "Oops, it feels deadly cold!");
		}
	}

	if (who->type == PLAYER)
	{
		/* If multiple objects were applied, update both slots */
		if (tmp)
		{
			esrv_send_item(who, tmp);
		}

		esrv_send_item(who, op);
	}

	return 0;
}