Beispiel #1
0
void menu_go(menuNode** menu, Controls* control){
	move_arrow(&((*menu)->arrowLevel), &control->jsY, (*menu)->nChildren);
	
	OLED_clear();
	OLED_print((*menu)->text,0,0);	//Prints the title
	
	//Iterates through submenues and prints them
	for(int i=1; i<=(*menu)->nChildren; ++i){
		//Prints a spaceinvader at the current arrow level.
		if((*menu)->arrowLevel == i){
			OLED_print("-s",i,0);
		}
		else{
			OLED_print("  ",i,0);
		}
		//The menu text is offset to the right by 2 to make room for the possible arrow
		OLED_print((*menu)->child[i-1]->text,i,2); 
	}
	
	//Left/right joystick changes the menu level.
	//Go to the child currently pointed at
	if(control->jsX.descreet_edge > 0){
		if((*menu)->arrowLevel !=0  &&((*menu)->arrowLevel <= (*menu)->nChildren)){
			*menu = (*menu)->child[((*menu)->arrowLevel)-1];
		}
	}
	//Go to parent
	else if(control->jsX.descreet_edge < 0){
		if((*menu)->parent != NULL){
			*menu = (*menu)->parent;
		}
	}
}
Beispiel #2
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);
	}
}
Beispiel #3
0
/**
 * Player fires a bow.
 * @param op Object firing.
 * @param dir Direction to fire. */
static void fire_bow(object *op, int dir)
{
	object *left_cont, *bow, *arrow = NULL, *left, *tmp_op;
	tag_t left_tag;

	/* If no dir is specified, attempt to find get the direction from
	 * player's target. */
	if (!dir && op->type == PLAYER && OBJECT_VALID(CONTR(op)->target_object, CONTR(op)->target_object_count))
	{
		rv_vector range_vector;
		dir = get_dir_to_target(op, CONTR(op)->target_object, &range_vector);
	}

	if (!dir)
	{
		new_draw_info(NDI_UNIQUE, op, "You can't shoot yourself!");
		return;
	}

	bow = CONTR(op)->equipment[PLAYER_EQUIP_BOW];

	if (!bow)
	{
		LOG(llevBug, "BUG: fire_bow(): bow without activated bow (%s - %d).\n", op->name, dir);
	}

	if (!bow->race)
	{
		new_draw_info_format(NDI_UNIQUE, op, "Your %s is broken.", bow->name);
		return;
	}

	if ((arrow = find_arrow_ext(op, bow->race, CONTR(op)->firemode_tag2)) == NULL)
	{
		new_draw_info_format(NDI_UNIQUE, op, "You have no %s left.", bow->race);
		return;
	}

	if (wall(op->map, op->x + freearr_x[dir], op->y + freearr_y[dir]))
	{
		new_draw_info(NDI_UNIQUE, op, "Something is in the way.");
		return;
	}

	/* This should not happen, but sometimes does */
	if (arrow->nrof == 0)
	{
		LOG(llevDebug, "BUG?: arrow->nrof == 0 in fire_bow() (%s)\n", query_name(arrow, NULL));
		remove_ob(arrow);
		return;
	}

	/* These are arrows left to the player */
	left = arrow;
	left_tag = left->count;
	left_cont = left->env;
	arrow = get_split_ob(arrow, 1, NULL, 0);
	set_owner(arrow, op);
	arrow->direction = dir;
	arrow->x = op->x;
	arrow->y = op->y;
	arrow->speed = 1;

	/* Now the trick: we transfer the shooting speed in the used
	 * skill - that will allow us to use "set_skill_speed() as global
	 * function. */
	op->chosen_skill->stats.maxsp = bow->stats.sp + arrow->last_grace;
	update_ob_speed(arrow);
	arrow->speed_left = 0;
	SET_ANIMATION(arrow, (NUM_ANIMATIONS(arrow) / NUM_FACINGS(arrow)) * dir);
	/* Save original wc and dam */
	arrow->last_heal = arrow->stats.wc;
	/* Will be put back in fix_arrow() */
	arrow->stats.hp = arrow->stats.dam;

	/* Now we do this: arrow wc = wc base from skill + (wc arrow + magic) + (wc range weapon bonus + magic) */
	if ((tmp_op = SK_skill(op)))
	{
		/* wc is in last heal */
		arrow->stats.wc += tmp_op->last_heal;
	}
	else
	{
		arrow->stats.wc += 10;
	}

	/* Now we determine how many tiles the arrow will fly. Again we use
	 * the skill base and add arrow + weapon values - but no magic add
	 * here. */
	arrow->last_sp = tmp_op->last_sp + bow->last_sp + arrow->last_sp;

	/* Add in all our wc bonus */
	arrow->stats.wc += (bow->magic + arrow->magic + SK_level(op) + thaco_bonus[op->stats.Dex] + bow->stats.wc);
	arrow->stats.wc_range = bow->stats.wc_range;
	arrow->stats.dam += dam_bonus[op->stats.Str] / 2 + bow->stats.dam + bow->magic + arrow->magic;
	arrow->stats.dam = FABS((int) ((float) (arrow->stats.dam * LEVEL_DAMAGE(SK_level(op)))));

	/* Adjust with the lower of condition */
	if (bow->item_condition > arrow->item_condition)
	{
		arrow->stats.dam = (sint16) (((float) arrow->stats.dam / 100.0f) * (float) arrow->item_condition);
	}
	else
	{
		arrow->stats.dam = (sint16) (((float) arrow->stats.dam / 100.0f) * (float) bow->item_condition);
	}

	arrow->level = SK_level(op);
	arrow->map = op->map;
	SET_MULTI_FLAG(arrow, FLAG_FLYING);
	SET_FLAG(arrow, FLAG_IS_MISSILE);
	SET_FLAG(arrow, FLAG_FLY_ON);
	SET_FLAG(arrow, FLAG_WALK_ON);
	/* Temporary buffer for "tiles to fly" */
	arrow->stats.grace = arrow->last_sp;
	/* Reflection timer */
	arrow->stats.maxgrace = 60 + (RANDOM() % 12);
	play_sound_map(op->map, op->x, op->y, SOUND_FIRE_ARROW, SOUND_NORMAL);

	if (insert_ob_in_map(arrow, op->map, op, 0))
	{
		move_arrow(arrow);
	}

	if (was_destroyed(left, left_tag))
	{
		esrv_del_item(CONTR(op), left_tag, left_cont);
	}
	else
	{
		esrv_send_item(op, left);
	}
}