示例#1
0
// handle events
int Enemy::eventHandler(df::Event *p_e){

	df::LogManager &lm = df::LogManager::getInstance();
	lm.writeLog("EVENT WITH IN ENEMY %s\n\n", p_e->getType().c_str());

	// if event is event hero position then set heros new position
	if (p_e->getType() == EVENT_HERO_POSITION){
		df::LogManager::getInstance().writeLog("got eventheroposition\n");
		setHeroPosition(static_cast <EventHeroPosition *> (p_e));
	}

	if (p_e->getType() == DF_COLLISION_EVENT){
		eventCollision(static_cast <df::EventCollision *> (p_e));
	}
	// if its a step event then make a move based on heros current position
	if (p_e->getType() == DF_STEP_EVENT){
		makeMove();
		if (power_countdown != 0) {
			power_countdown--;
		}
		else {
			if (power != NONE){
				if (power == SLOWENEMY) {
					move_slowdown = move_slowdown / 2;
				}
				power = NONE;
			}
		}

		if (updatePathSlowdown < 0){
			// get path to hero
			TreeNode *base = new TreeNode(df::Position(getPosition().getX(), getPosition().getY() + 1));
			pathToHero = TreeNode::pathToPosition(base, heroPosition, &sizeOfPath, 3, false);
			updatePathSlowdown = 50;
			counterOfPath = 0;
		}
		updatePathSlowdown--;
	}

	if (p_e->getType() == DF_POWER_EVENT) {
		handlePower(static_cast <EventPower *> (p_e));
	}
	return 0;
}
示例#2
0
/**
 * logic()
 * Handle a single frame.  This includes:
 * - move the avatar based on buttons pressed
 * - calculate the next frame of animation
 * - calculate camera position based on avatar position
 *
 * @param action The actionbar power activated and the target.  action.power == 0 means no power.
 * @param restrict_power_use Whether or not to allow power usage on mouse1
 * @param npc True if the player is talking to an NPC. Can limit ability to move/attack in certain conditions
 */
void Avatar::logic(std::vector<ActionData> &action_queue, bool restrict_power_use, bool npc) {

	// hazards are processed after Avatar and Enemy[]
	// so process and clear sound effects from previous frames
	// check sound effects
	if (AUDIO) {
		if (play_sfx_phys)
			snd->play(sound_melee, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);
		if (play_sfx_ment)
			snd->play(sound_mental, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);
		if (play_sfx_hit)
			snd->play(sound_hit, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);
		if (play_sfx_die)
			snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);
		if (play_sfx_critdie)
			snd->play(sound_die, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);
		if(play_sfx_block)
			snd->play(sound_block, GLOBAL_VIRTUAL_CHANNEL, stats.pos, false);

		// clear sound flags
		play_sfx_hit = false;
		play_sfx_phys = false;
		play_sfx_ment = false;
		play_sfx_die = false;
		play_sfx_critdie = false;
		play_sfx_block = false;
	}

	// clear current space to allow correct movement
	mapr->collider.unblock(stats.pos.x, stats.pos.y);

	// turn on all passive powers
	if ((stats.hp > 0 || stats.effects.triggered_death) && !respawn && !transform_triggered) powers->activatePassives(&stats);
	if (transform_triggered) transform_triggered = false;

	// handle when the player stops blocking
	if (stats.effects.triggered_block && !stats.blocking) {
		stats.cur_state = AVATAR_STANCE;
		stats.effects.triggered_block = false;
		stats.effects.clearTriggerEffects(TRIGGER_BLOCK);
		stats.refresh_stats = true;
	}

	stats.logic();

	bool allowed_to_move;
	bool allowed_to_use_power = true;

#ifdef __ANDROID__
	const bool click_to_respawn = true;
#else
	const bool click_to_respawn = false;
#endif

	// check for revive
	if (stats.hp <= 0 && stats.effects.revive) {
		stats.hp = stats.get(STAT_HP_MAX);
		stats.alive = true;
		stats.corpse = false;
		stats.cur_state = AVATAR_STANCE;
	}

	// check level up
	if (stats.level < static_cast<int>(stats.xp_table.size()) && stats.xp >= stats.xp_table[stats.level]) {
		stats.level_up = true;
		stats.level++;
		std::stringstream ss;
		ss << msg->get("Congratulations, you have reached level %d!", stats.level);
		if (stats.level < stats.max_spendable_stat_points) {
			ss << " " << msg->get("You may increase one attribute through the Character Menu.");
			newLevelNotification = true;
		}
		log_msg = ss.str();
		stats.recalc();
		snd->play(sound_levelup);

		// if the player managed to level up while dead (e.g. via a bleeding creature), restore to life
		if (stats.cur_state == AVATAR_DEAD) {
			stats.cur_state = AVATAR_STANCE;
		}
	}

	// check for bleeding to death
	if (stats.hp == 0 && !(stats.cur_state == AVATAR_DEAD)) {
		stats.effects.triggered_death = true;
		stats.cur_state = AVATAR_DEAD;
	}

	// assist mouse movement
	if (!inpt->pressing[MAIN1]) {
		drag_walking = false;
	}

	// block some interactions when attacking
	if (!inpt->pressing[MAIN1] && !inpt->pressing[MAIN2]) {
		stats.attacking = false;
	}
	else if((inpt->pressing[MAIN1] && !inpt->lock[MAIN1]) || (inpt->pressing[MAIN2] && !inpt->lock[MAIN2])) {
		stats.attacking = true;
	}

	// handle animation
	if (!stats.effects.stun) {
		activeAnimation->advanceFrame();
		for (unsigned i=0; i < anims.size(); i++) {
			if (anims[i] != NULL)
				anims[i]->advanceFrame();
		}
	}

	if (target_anim && target_anim->getTimesPlayed() >= 1) {
		target_visible = false;
		target_anim->reset();
	}

	if (target_anim && target_visible)
		target_anim->advanceFrame();

	// change the cursor if we're attacking
	if (action_queue.empty()) {
		lock_cursor = false;
	}
	else if (lock_cursor) {
		curs->setCursor(CURSOR_ATTACK);
	}

	// save a valid tile position in the event that we untransform on an invalid tile
	if (stats.transformed && mapr->collider.is_valid_position(stats.pos.x,stats.pos.y,MOVEMENT_NORMAL, true)) {
		transform_pos = stats.pos;
		transform_map = mapr->getFilename();
	}

	switch(stats.cur_state) {
		case AVATAR_STANCE:

			setAnimation("stance");

			// allowed to move or use powers?
			if (MOUSE_MOVE) {
				allowed_to_move = restrict_power_use && (!inpt->lock[MAIN1] || drag_walking) && !lockAttack && !npc;
				allowed_to_use_power = !allowed_to_move;
			}
			else {
				allowed_to_move = true;
				allowed_to_use_power = true;
			}

			// handle transitions to RUN
			if (allowed_to_move)
				set_direction();

			if (pressing_move() && allowed_to_move) {
				if (MOUSE_MOVE && inpt->pressing[MAIN1]) {
					inpt->lock[MAIN1] = true;
					drag_walking = true;
				}

				if (move()) { // no collision
					stats.cur_state = AVATAR_RUN;
				}
			}

			if (MOUSE_MOVE && !inpt->pressing[MAIN1]) {
				inpt->lock[MAIN1] = false;
				lockAttack = false;
			}

			break;

		case AVATAR_RUN:

			setAnimation("run");

			if (!sound_steps.empty()) {
				int stepfx = rand() % static_cast<int>(sound_steps.size());

				if (activeAnimation->isFirstFrame() || activeAnimation->isActiveFrame())
					snd->play(sound_steps[stepfx]);
			}

			// allowed to move or use powers?
			if (MOUSE_MOVE) {
				allowed_to_use_power = !(restrict_power_use && !inpt->lock[MAIN1]);
			}
			else {
				allowed_to_use_power = true;
			}

			// handle direction changes
			set_direction();

			// handle transition to STANCE
			if (!pressing_move()) {
				stats.cur_state = AVATAR_STANCE;
				break;
			}
			else if (!move()) { // collide with wall
				stats.cur_state = AVATAR_STANCE;
				break;
			}

			if (activeAnimation->getName() != "run")
				stats.cur_state = AVATAR_STANCE;

			break;

		case AVATAR_ATTACK:

			setAnimation(attack_anim);

			if (MOUSE_MOVE) lockAttack = true;

			if (activeAnimation->isFirstFrame() && attack_anim == "swing")
				snd->play(sound_melee);

			if (activeAnimation->isFirstFrame() && attack_anim == "cast")
				snd->play(sound_mental);

			// do power
			if (activeAnimation->isActiveFrame()) {
				// some powers check if the caster is blocking a tile
				// so we block the player tile prematurely here
				mapr->collider.block(stats.pos.x, stats.pos.y, false);

				powers->activate(current_power, &stats, act_target);
				hero_cooldown[current_power] = powers->getPower(current_power).cooldown;
			}

			if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != attack_anim) {
				stats.cur_state = AVATAR_STANCE;
				stats.cooldown_ticks += stats.cooldown;
			}

			break;

		case AVATAR_BLOCK:

			setAnimation("block");

			stats.blocking = false;

			break;

		case AVATAR_HIT:

			setAnimation("hit");

			if (activeAnimation->isFirstFrame()) {
				stats.effects.triggered_hit = true;
			}

			if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "hit") {
				stats.cur_state = AVATAR_STANCE;
			}

			break;

		case AVATAR_DEAD:
			allowed_to_use_power = false;

			if (stats.effects.triggered_death) break;

			if (stats.transformed) {
				stats.transform_duration = 0;
				untransform();
			}

			setAnimation("die");

			if (!stats.corpse && activeAnimation->isFirstFrame() && activeAnimation->getTimesPlayed() < 1) {
				stats.effects.clearEffects();

				// raise the death penalty flag.  Another module will read this and reset.
				stats.death_penalty = true;

				// close menus in GameStatePlay
				close_menus = true;

				snd->play(sound_die);

				if (stats.permadeath) {
					log_msg = msg->get("You are defeated. Game over! Press Enter to exit to Title.");
				}
				else {
					log_msg = msg->get("You are defeated. Press Enter to continue.");
				}

				// if the player is attacking, we need to block further input
				if (inpt->pressing[MAIN1])
					inpt->lock[MAIN1] = true;
			}

			if (activeAnimation->getTimesPlayed() >= 1 || activeAnimation->getName() != "die") {
				stats.corpse = true;
			}

			// allow respawn with Accept if not permadeath
			if (inpt->pressing[ACCEPT] || (click_to_respawn && inpt->pressing[MAIN1] && !inpt->lock[MAIN1])) {
				if (inpt->pressing[ACCEPT]) inpt->lock[ACCEPT] = true;
				if (click_to_respawn && inpt->pressing[MAIN1]) inpt->lock[MAIN1] = true;
				mapr->teleportation = true;
				mapr->teleport_mapname = mapr->respawn_map;
				if (stats.permadeath) {
					// set these positions so it doesn't flash before jumping to Title
					mapr->teleport_destination.x = stats.pos.x;
					mapr->teleport_destination.y = stats.pos.y;
				}
				else {
					respawn = true;

					// set teleportation variables.  GameEngine acts on these.
					mapr->teleport_destination.x = mapr->respawn_point.x;
					mapr->teleport_destination.y = mapr->respawn_point.y;
				}
			}

			break;

		default:
			break;
	}

	// handle power usage
	if (allowed_to_use_power)
		handlePower(action_queue);

	// calc new cam position from player position
	// cam is focused at player position
	mapr->cam.x = stats.pos.x;
	mapr->cam.y = stats.pos.y;

	// check for map events
	mapr->checkEvents(stats.pos);

	// decrement all cooldowns
	for (unsigned i = 0; i < hero_cooldown.size(); i++) {
		hero_cooldown[i]--;
		if (hero_cooldown[i] < 0) hero_cooldown[i] = 0;
	}

	// make the current square solid
	mapr->collider.block(stats.pos.x, stats.pos.y, false);
}