void PlayerInst::use_move(GameState* gs, const GameAction& action) {
	perf_timer_begin(FUNCNAME);
	int dx = action.action_x;
	int dy = action.action_y;

	float mag = effective_stats().movespeed;

	float ddx = dx * mag;
	float ddy = dy * mag;

	EnemyInst* target = NULL;
//Enemy hitting test for melee
	gs->object_radius_test(this, (GameInst**)&target, 1, &enemy_colfilter,
			x + ddx * 2, y + ddy * 2);

//Smaller radius enemy pushing test, can intercept enemy radius but not too far
	EnemyInst* alreadyhitting[5] = { 0, 0, 0, 0, 0 };
	gs->object_radius_test(this, (GameInst**)alreadyhitting, 5,
			&enemy_colfilter, x, y, radius);
	bool already = false;
	for (int i = 0; i < 5; i++) {
		if (alreadyhitting[i]) {
			if (ddx < 0 == ((alreadyhitting[i]->x - x + ddx * 2) < 0)) {
				ddx = 0;
			}
			if (ddy < 0 == ((alreadyhitting[i]->y - y + ddy * 2) < 0)) {
				ddy = 0;
			}
			already = true;
		}
	}

	Pos newpos(round(rx + ddx), round(ry + ddy));

	if (!gs->tile_radius_test(newpos.x, newpos.y, radius)) {
		vx = ddx;
		vy = ddy;
	} else if (!gs->tile_radius_test(newpos.x, y, radius)) {
		vx = ddx;
	} else if (!gs->tile_radius_test(x, newpos.y, radius)) {
		vy = ddy;
	} else if (ddx != 0 && ddy != 0) {
		//Alternatives in opposite directions for x & y
		Pos newpos_alt1(round(vx + ddx), round(vy - ddy));
		Pos newpos_alt2(round(vx - ddx), round(vy + ddy));
		if (!gs->tile_radius_test(newpos_alt1.x, newpos_alt1.y, radius)) {
			vx += ddx;
			vy -= ddy;
		} else if (!gs->tile_radius_test(newpos_alt2.x, newpos_alt2.y,
				radius)) {
			vx -= ddx;
			vy += ddy;
		}

	}

	event_log("Player id: %d using move for turn %d, vx=%f, vy=%f\n", id, gs->frame(), vx, vy);
	perf_timer_end(FUNCNAME);
}
Beispiel #2
0
// Frame event handling
void ActionBar::draw(GameState* gs) const {
	perf_timer_begin(FUNCNAME);
	PlayerInst* player = gs->local_player();

	draw_player_weapon_actionbar(gs, player, bbox.x1, bbox.y1);
	draw_player_spell_actionbar(gs, player,
			BBox(bbox.x1 + EQUIP_SLOT_WIDTH, bbox.y1, bbox.x2, bbox.y2));
	perf_timer_end(FUNCNAME);
}
Beispiel #3
0
/* General gl_print function for others to delegate to */
static Dim gl_print_impl(const font_data& font, const Colour& c, Pos p,
		int max_width, bool center_x, bool center_y, bool actually_print,
		const char* fmt, va_list ap) {
	perf_timer_begin(FUNCNAME);
	char text[512];
	vsnprintf(text, 512, fmt, ap);
	va_end(ap);

	Dim offset(0, 0);

	std::vector<int> line_splits;
	int measured_width = process_string(font, text, max_width, line_splits);

	if (center_x) {
		p.x -= measured_width / 2;
	}
	if (center_y) {
		p.y -= font.h * line_splits.size() / 2;
	}

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, font.font_img.texture);

	glColor4ub(c.r, c.g, c.b, c.a);
	glBegin(GL_QUADS);
	for (int linenum = 0, i = 0; linenum < line_splits.size(); linenum++) {
		int len = 0;
		int eol = line_splits[linenum];

		offset.h += font.h;

		for (; i < eol; i++) {
			unsigned char chr = text[i];
			if (chr == '\n') {
				continue; //skip newline char
			}
			const char_data& cdata = font.data[chr];
			len += cdata.advance;
			if (actually_print) {
				gl_draw_glyph(font, chr,
						p.x + len - (cdata.advance - cdata.left),
						p.y + offset.h - cdata.move_up, c);
			}
		}
		offset.w = std::max(len, offset.w);
		offset.h += 1;
	}
	glEnd();
	glDisable(GL_TEXTURE_2D);
	perf_timer_end(FUNCNAME);
	return offset;
}
void PlayerInst::perform_queued_actions(GameState* gs) {
	perf_timer_begin(FUNCNAME);
	GameSettings& settings = gs->game_settings();

	if (settings.saving_to_action_file()) {
		save_actions(gs, queued_actions);
	}

	for (int i = 0; i < queued_actions.size(); i++) {
		perform_action(gs, queued_actions[i]);
	}
	queued_actions.clear();
	actions_set_for_turn = false;
	perf_timer_end(FUNCNAME);
}
Beispiel #5
0
void GameHud::draw(GameState* gs) {
	perf_timer_begin(FUNCNAME);
	gl_set_drawing_area(0, 0, sidebar_box.x2, sidebar_box.y2);
	gl_draw_rectangle(sidebar_box.x1, sidebar_box.y1, width(), height(),
			bg_colour);

	PlayerInst* player_inst = gs->local_player();
	if (!player_inst)
		return;

	action_bar.draw(gs);
	sidebar.draw(gs);
	// Must draw console after other components have chance to draw content there
	console.draw(gs);
	perf_timer_end(FUNCNAME);
}
Beispiel #6
0
int GameNetConnection::poll_messages(int timeout) {
    if (_connection) {
        for (int i = 0; i < _delayed_messages.size(); i++) {
            QueuedMessage& qm = _delayed_messages[i];
            if (_handle_message(qm.sender, *qm.message)) {
                delete qm.message;
                _delayed_messages.erase(_delayed_messages.begin() + i);
                i--;
            }
        }
        perf_timer_begin("*** NETWORK POLLING ***");
        int polln = _connection->poll(gamenetconnection_consume_message, (void*) this,
                timeout);
        perf_timer_end("*** NETWORK POLLING ***");
        return polln;
    }
    return 0;
}
Beispiel #7
0
void GameChat::draw_player_chat(GameState* gs) const {
	perf_timer_begin(FUNCNAME);
	const ldraw::Font& font = gs->font();
	const int padding = 5;
	int line_sep = font.height() + 2;

	Size vsize(gs->view().size());
	Size chat_size(vsize.w, 100);
	Pos chat_pos(0, 0);
	Pos text_pos(chat_pos.x + padding, chat_pos.y + padding);

	ldraw::draw_rectangle(COL_CONSOLE_BOX.alpha(50 * fade_out),
			BBox(chat_pos, chat_size));

	bool draw_typed_message = is_typing || !typing_field.empty();

	int start_msg = 0;
	int message_space = chat_size.h - padding * 2
			- (draw_typed_message ? line_sep : 0);
	int msgs_in_screen = message_space / line_sep;
	if (messages.size() > msgs_in_screen) {
		start_msg = messages.size() - msgs_in_screen;
	}

	for (int i = start_msg; i < messages.size(); i++) {
		messages[i].draw(font, fade_out, text_pos);
		text_pos.y += line_sep;
	}

	if (draw_typed_message) {
		int type_y = chat_pos.y + chat_size.h - padding - line_sep;

		ldraw::draw_line(Colour(200, 200, 200, fade_out * 180),
				Pos(chat_pos.x, type_y), Pos(chat_pos.x + chat_size.w, type_y));
		ChatMessage typed_message = get_field_as_chat_message(gs, false);
		typed_message.draw(font, fade_out,
				Pos(text_pos.x, type_y + padding - 1));
	}
	perf_timer_end(FUNCNAME);
}
Beispiel #8
0
void GameChat::draw_player_chat(GameState* gs) const {
	perf_timer_begin(FUNCNAME);
	const font_data& font = gs->primary_font();
	const int padding = 5;
	int line_sep = font.h + 2;

	int view_w = gs->view().width, view_h = gs->view().height;
	int chat_w = view_w, chat_h = 100;
	int chat_x = 0, chat_y = 0; //h - chat_h - TILE_SIZE;
	int text_x = chat_x + padding, text_y = chat_y + padding;

	gl_draw_rectangle(chat_x, chat_y, chat_w, chat_h,
			COL_CONSOLE_BOX.with_alpha(50 * fade_out));

	bool draw_typed_message = is_typing || !typed_message.empty();

	int start_msg = 0;
	int message_space = chat_h - padding * 2
			- (draw_typed_message ? line_sep : 0);
	int msgs_in_screen = message_space / line_sep;
	if (messages.size() > msgs_in_screen) {
		start_msg = messages.size() - msgs_in_screen;
	}

	for (int i = start_msg; i < messages.size(); i++) {
		messages[i].draw(font, fade_out, text_x, text_y);
		text_y += line_sep;
	}

	if (draw_typed_message) {
		int type_y = chat_y + chat_h - padding - line_sep;
		gl_draw_line(chat_x, type_y, chat_x + chat_w, type_y,
				Colour(200, 200, 200, fade_out * 180));
		typed_message.draw(font, fade_out, text_x, type_y + padding - 1);
	}
	perf_timer_end(FUNCNAME);
}
void MonsterController::pre_step(GameState* gs) {
	perf_timer_begin(FUNCNAME);

	CollisionAvoidance& coll_avoid = gs->collision_avoidance();
	PlayerInst* local_player = gs->local_player();
	std::vector<EnemyOfInterest> eois;

	players = gs->players_in_level();

	//Update 'mids' to only hold live objects
	std::vector<obj_id> mids2;
	mids2.reserve(mids.size());
	mids.swap(mids2);

	for (int i = 0; i < mids2.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids2[i]);
		if (e == NULL)
			continue;
		EnemyBehaviour& eb = e->behaviour();
		eb.step();

		//Add live instances back to monster id list
		mids.push_back(mids2[i]);

		int closest_player_index = find_player_to_target(gs, e);

		if (eb.current_action == EnemyBehaviour::INACTIVE
				&& e->cooldowns().is_hurting()) {
			eb.current_action = EnemyBehaviour::CHASING_PLAYER;
		}
		if (closest_player_index == -1
				&& eb.current_action == EnemyBehaviour::CHASING_PLAYER) {
			eb.current_action = EnemyBehaviour::INACTIVE;
			e->target() = NONE;
		}

		if (eb.current_action == EnemyBehaviour::CHASING_PLAYER)
			eois.push_back(
					EnemyOfInterest(e, closest_player_index,
							inst_distance(e, players[closest_player_index])));
		else if (eb.current_action == EnemyBehaviour::INACTIVE)
			monster_wandering(gs, e);
		else
			//if (eb.current_action == EnemyBehaviour::FOLLOWING_PATH)
			monster_follow_path(gs, e);
	}

	set_monster_headings(gs, eois);

	//Update player positions for collision avoidance simulator
	for (int i = 0; i < players.size(); i++) {
		PlayerInst* p = players[i];
		coll_avoid.set_position(p->collision_simulation_id(), p->x, p->y);
	}

	for (int i = 0; i < mids.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids[i]);
		lua_State* L = gs->luastate();
		lua_gameinst_callback(L, e->etype().step_event.get(L), e);
		update_velocity(gs, e);
		simul_id simid = e->collision_simulation_id();
		coll_avoid.set_position(simid, e->rx, e->ry);
		coll_avoid.set_preferred_velocity(simid, e->vx, e->vy);
	}

	coll_avoid.step();

	for (int i = 0; i < mids.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids[i]);
		update_position(gs, e);
	}

	perf_timer_end(FUNCNAME);
}