示例#1
0
static bool handle_spell_slot_io(GameState* gs, PlayerInst* p, const BBox& bbox,
		ActionQueue& queued_actions) {
	int mx = gs->mouse_x(), my = gs->mouse_y();
	bool leftdown = gs->mouse_left_down(), rightdown = gs->mouse_right_down();

	/* Check if a spell is selected */
	int spell_slot = get_selected_slot(bbox, mx, my);

	if (leftdown && spell_slot > -1) {
		if (spell_slot < p->spells_known().amount()) {
			queued_actions.push_back(
					game_action(gs, p, GameAction::CHOSE_SPELL, spell_slot));
		}
		return true; // Ensures mouse actions are filtered when clicking on action bar
	}

	if (rightdown && spell_slot > -1) {
		if (spell_slot < p->spells_known().amount()) {
			queued_actions.push_back(
					game_action(gs, p, GameAction::CHOSE_SPELL, -1));
		}
		return true; // Ensures mouse actions are filtered when clicking on action bar
	}
	return false;
}
示例#2
0
static bool handle_equip_slot_io(GameState* gs, PlayerInst* p, const BBox& bbox,
		ActionQueue& queued_actions) {
	int mx = gs->mouse_x(), my = gs->mouse_y();
	bool leftdown = gs->mouse_left_down(), rightdown = gs->mouse_right_down();

	/* Check whether to de-equip weapon */
	if (rightdown && is_within_equipped_weapon(bbox, mx, my)) {
		queued_actions.push_back(
				game_action(gs, p, GameAction::DEEQUIP_ITEM,
						EquipmentEntry::WEAPON));
		return true;
	}

	/* Check whether to de-equip projectile */
	if (rightdown && is_within_equipped_projectile(bbox, mx, my)) {
		if (!p->projectile().empty()) {
			queued_actions.push_back(
					game_action(gs, p, GameAction::DEEQUIP_ITEM,
							EquipmentEntry::AMMO));
			return true;
		}
	}

	/* Check whether to select weapon as active action */
	bool selects_projectile = !p->projectile().empty()
			&& is_within_equipped_projectile(bbox, mx, my);
	if (leftdown
			&& (is_within_equipped_weapon(bbox, mx, my) || selects_projectile)) {
		queued_actions.push_back(
				game_action(gs, p, GameAction::CHOSE_SPELL, -1));
		return true;
	}
	return false;
}
示例#3
0
static bool queue_portal_use(GameState* gs, PlayerInst* player, ActionQueue& queue) {
	FeatureInst* portal = find_usable_portal(gs, player);
	if (portal != NULL) {
		queue.push_back(
				game_action(gs, player, GameAction::USE_PORTAL));
		return true;
	}
	return false;
}
示例#4
0
bool InventoryContent::handle_io(GameState* gs, ActionQueue& queued_actions) {
	PlayerInst* p = gs->local_player();
	Inventory& inv = p->inventory();
	int mx = gs->mouse_x(), my = gs->mouse_y();
	bool within_inventory = bbox.contains(mx, my);

	/* Use an item */
	if (gs->mouse_left_click() && within_inventory) {

		int slot = get_itemslotn(inv, bbox, mx, my);
		if (slot >= 0 && slot < INVENTORY_SIZE && inv.get(slot).amount > 0) {
			queued_actions.push_back(
					game_action(gs, p, GameAction::USE_ITEM, slot, p->x, p->y));
			return true;
		}
	}

	/* Start dragging an item */
	if (gs->mouse_right_click() && within_inventory) {
		int slot = get_itemslotn(inv, bbox, mx, my);
		if (slot != -1 && inv.slot_filled(slot)) {
			slot_selected = slot;
			return true;
		}
	}

	/* Drop a dragged item */
	if (slot_selected > -1 && gs->mouse_right_release()) {
		int slot = get_itemslotn(inv, bbox, mx, my);

		if (slot == -1 || slot == slot_selected) {
			queued_actions.push_back(
					game_action(gs, p, GameAction::DROP_ITEM, slot_selected));
		} else {
			queued_actions.push_back(
					game_action(gs, p, GameAction::REPOSITION_ITEM,
							slot_selected, 0, 0, slot));
		}
		return true;
	}

	return false;
}
void PlayerInst::enqueue_not_enough_mana_actions(GameState* gs) {
    const int AUTOUSE_MANA_POTION_CNT = 2;
    int item_slot = inventory().find_slot(get_item_by_name("Mana Potion"));
    if (gs->game_settings().autouse_mana_potions
            && autouse_mana_potion_try_count >= AUTOUSE_MANA_POTION_CNT
            && item_slot != -1) {
        queued_actions.push_back(
            game_action(gs, this, GameAction::USE_ITEM, item_slot));
        autouse_mana_potion_try_count = 0;
    } else {
        autouse_mana_potion_try_count++;
    }
}
示例#6
0
static bool handle_io_spells_known(GameState* gs, ActionQueue& queued_actions,
		const BBox& bbox, SpellsKnown& spells, int ind_low, int ind_high) {
	const int spell_n = spells.amount();
	int mx = gs->mouse_x(), my = gs->mouse_y();
	int spellidx = ind_low;

	int x = bbox.x1, ex = bbox.x2;
	for (int y = bbox.y1; y < bbox.y2; y += TILE_SIZE) {
		if (spellidx >= spell_n)
			break;

		BBox entry_box(x, y, ex - 2, y + TILE_SIZE);
		if (entry_box.contains(mx, my) && gs->mouse_left_click()) {
			queued_actions.push_back(
					game_action(gs, gs->local_player(), GameAction::CHOSE_SPELL,
							spellidx));
			return true;
		}
		spellidx++;
	}
	return false;
}
示例#7
0
void PlayerInst::enqueue_io_movement_actions(GameState* gs, int& dx, int& dy) {
//Arrow/wasd movement
	if (gs->key_down_state(SDLK_UP) || gs->key_down_state(SDLK_w)) {
		dy -= 1;
	}
	if (gs->key_down_state(SDLK_RIGHT) || gs->key_down_state(SDLK_d)) {
		dx += 1;
	}
	if (gs->key_down_state(SDLK_DOWN) || gs->key_down_state(SDLK_s)) {
		dy += 1;
	}
	if (gs->key_down_state(SDLK_LEFT) || gs->key_down_state(SDLK_a)) {
		dx -= 1;
	}
	if (dx != 0 || dy != 0) {
		queued_actions.push_back(
				game_action(gs, this, GameAction::MOVE, 0, dx, dy));
		moving = true;
	} else {
		moving = false;
	}
}
示例#8
0
bool StoreContent::handle_io(GameState* gs, ActionQueue& queued_actions) {
	PlayerInst* p = gs->local_player();
	StoreInventory& inv = store_inventory();
	int mx = gs->mouse_x(), my = gs->mouse_y();
	bool within_inventory = bbox.contains(mx, my);

	/* Buy an item (left click) */
	if (gs->mouse_left_click() && within_inventory) {

		int slot = get_itemslotn(inv, bbox, mx, my);
		if (slot >= 0 && slot < INVENTORY_SIZE && inv.get(slot).amount > 0) {
			if (p->gold() >= inv.get(slot).cost) {
				queued_actions.push_back(
						game_action(gs, p, GameAction::PURCHASE_FROM_STORE,
								store_object->id, NONE, NONE, slot));
			} else {
				gs->game_chat().add_message("You cannot afford it!",
						COL_PALE_RED);
			}
			return true;
		}
	}
	return false;
}
// dx & dy indicates moving direction, useful for choosing melee attack targets
bool PlayerInst::enqueue_io_spell_and_attack_actions(GameState* gs, float dx,
        float dy) {
    GameView& view = gs->view();
    WeaponEntry& wentry = weapon().weapon_entry();

    bool mouse_within = gs->mouse_x() < gs->view().width;
    int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y();

    int level = gs->get_level()->id(), frame = gs->frame();

    bool is_moving = (dx != 0.0f || dy != 0.0f);
    IOController& io = gs->io_controller();
    bool attack_used = enqueue_io_spell_actions(gs);

    bool autotarget = io.query_event(IOEvent::AUTOTARGET_CURRENT_ACTION)
                      || io.query_event(IOEvent::ACTIVATE_SPELL_N);
    bool mousetarget = io.query_event(IOEvent::MOUSETARGET_CURRENT_ACTION);

    bool weaponuse = spell_selected() == -1;

    // choose & use weapon
    if (io.query_event(IOEvent::USE_WEAPON)) {
        queued_actions.push_back(
            game_action(gs, this, GameAction::CHOSE_SPELL, -1));
        autotarget = true;
        weaponuse = true;
    }

    if (spell_selected() >= 0
            && spells_known().get_entry(spell_selected()).mp_cost
            > core_stats().mp) {
        weaponuse = true;
    }

    // weapon use
    if (!attack_used && weaponuse && (autotarget || mousetarget)) {

        bool is_projectile = wentry.uses_projectile
                             || equipment().has_projectile();

        MonsterController& mc = gs->monster_controller();
        GameInst* curr_target = gs->get_instance(current_target);
        GameInst* target = NULL;
        Pos targ_pos;

        if (is_projectile) {
            if (mousetarget) {
                targ_pos = Pos(rmx, rmy);
            } else if (autotarget && curr_target) {
                targ_pos = curr_target->pos();
            }
        } else {
            if (mousetarget) {
                dx = rmx - x, dy = rmy - y;
            }
            target = get_weapon_autotarget(gs, this, curr_target, dx, dy);
            if (target) {
                targ_pos = Pos(target->x, target->y);

            }
            if (!is_moving && !target && !mousetarget && spell_selected() == -1
                    && curr_target && !is_projectile) {
                int vx, vy;
                GameInst* closest = get_closest_monster(gs, this);

                if (closest
                        && decide_attack_movement(pos(), closest->pos(),
                                                  TILE_SIZE / 4, vx, vy)) {
                    queued_actions.push_back(
                        game_action(gs, this, GameAction::MOVE, spellselect,
                                    round(vx), round(vy)));
                }
            }
        }
        if (target || (is_projectile && (mousetarget || curr_target))) {
            queued_actions.push_back(
                game_action(gs, this, GameAction::USE_WEAPON, spellselect,
                            targ_pos.x, targ_pos.y));
            attack_used = true;
        }
    }
    return attack_used;
}
示例#10
0
bool PlayerInst::enqueue_io_spell_actions(GameState* gs) {
    GameView& view = gs->view();
    IOController& io = gs->io_controller();
    SpellsKnown& spells = spells_known();

    bool perform_spell = false;
    bool chose_spell = false;
    bool triggered_already = false;

    int newspell = spell_selected();
    //Spell choice
    for (int i = 0; i < spells.amount(); i++) {
        IOEvent event(IOEvent::ACTIVATE_SPELL_N, i);
        if (io.query_event(event, &triggered_already)) {
            chose_spell = true;
            // Use the remembered choice to determine if its appropriate to cast this spell
            // This makes sure the key must be hit once to switch spell, and again to use it
            if (spell_selected() == i
                    && previous_spellselect == spell_selected()) {
                //Double hit a spell switch to quick-perform it
                perform_spell = true;
            } else if (!triggered_already) {
                newspell = i;
            }
            break;
        }
    }
    if (!chose_spell) {
        // If we did not switch a spell with one of the quick-select keys, remember our choice
        previous_spellselect = spell_selected();

        if (io.query_event(IOEvent::TOGGLE_ACTION_UP)) {
            if (spells.amount() > 0) {
                newspell = (spell_selected() + 1) % spells.amount();
            }
        } else if (io.query_event(IOEvent::TOGGLE_ACTION_DOWN)) {
            if (spell_selected() <= 0) {
                newspell = spells.amount() - 1;
            } else {
                newspell = spell_selected() - 1;
            }
        }
    }

    if (newspell != spell_selected()) {
        queued_actions.push_back(
            game_action(gs, this, GameAction::CHOSE_SPELL, newspell));
    }

    bool auto_target = true;
    // We don't auto-target unless a mouse is not used
    if (!perform_spell
            && io.query_event(IOEvent::MOUSETARGET_CURRENT_ACTION,
                              &triggered_already)) {
        perform_spell = true;
        auto_target = false;

    } else if (!perform_spell) {
        perform_spell = io.query_event(IOEvent::AUTOTARGET_CURRENT_ACTION,
                                       &triggered_already);
    }
    if (spell_selected() > -1 && perform_spell) {
        SpellEntry& spl_entry = spells.get_entry(spell_selected());

        Pos target;
        bool can_trigger = !triggered_already
                           || spl_entry.can_cast_with_held_key;
        bool can_target;
        if (auto_target) {
            can_target = lua_spell_get_target(gs, this,
                                              spl_entry.autotarget_func, target);
        } else {
            int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y();
            target = Pos(rmx, rmy);
            can_target = true;
        }

        if (spl_entry.mp_cost > core_stats().mp) {
            if (!triggered_already && can_target) {
                enqueue_not_enough_mana_actions(gs);
            }
            return false;
        } else {
            autouse_mana_potion_try_count = 0;
        }

        if (can_trigger && can_target) {
            bool can_use = lua_spell_check_prereq(gs, this, spl_entry,
                                                  spl_entry.prereq_func, target);
            if (can_use) {
                queued_actions.push_back(
                    game_action(gs, this, GameAction::USE_SPELL,
                                spell_selected(), target.x, target.y));
                return true;
            } else if (!auto_target) {
                gs->game_chat().add_message("Target location is not valid.");
            }
        } else if (!triggered_already && !can_target) {
            gs->game_chat().add_message(
                "Cannot currently auto-target spell. Use manual controls (with mouse).");
        }
    }
    return false;
}
示例#11
0
void PlayerInst::enqueue_io_actions(GameState* gs) {
	LANARTS_ASSERT(is_local_player() && gs->local_player() == this);

	if (actions_set_for_turn) {
		return;
	}

	bool single_player = (gs->player_data().all_players().size() <= 1);

	actions_set_for_turn = true;

	GameSettings& settings = gs->game_settings();
	GameView& view = gs->view();

	PlayerDataEntry& pde = gs->player_data().local_player_data();

	if (pde.action_queue.has_actions_for_frame(gs->frame())) {
		pde.action_queue.extract_actions_for_frame(queued_actions, gs->frame());
		event_log("Player %d has %d actions", player_entry(gs).net_id,
				(int) queued_actions.size());
		return;
	}
	if (!single_player) {
		gs->set_repeat_actions_counter(settings.frame_action_repeat);
	}

	int dx = 0, dy = 0;
	bool mouse_within = gs->mouse_x() < gs->view().width;
	int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y();

	bool was_moving = moving, do_stopaction = false;
	IOController& io = gs->io_controller();

	if (!settings.loadreplay_file.empty()) {
		load_actions(gs, queued_actions);
	}

	enqueue_io_movement_actions(gs, dx, dy);

	if (was_moving && !moving && cooldowns().can_do_stopaction()) {
		do_stopaction = true;
	}
//Shifting target
	if (gs->key_press_state(SDLK_k)) {
		shift_autotarget(gs);
	}

	if (gs->key_press_state(SDLK_m))
		spellselect = -1;

	bool attack_used = false;
	if (!gs->game_hud().handle_io(gs, queued_actions)) {
		attack_used = enqueue_io_spell_and_attack_actions(gs, dx, dy);
		enqueue_io_equipment_actions(gs, do_stopaction);
	}

	bool action_usage = io.query_event(IOEvent::ACTIVATE_SPELL_N)
			|| io.query_event(IOEvent::USE_WEAPON)
			|| io.query_event(IOEvent::AUTOTARGET_CURRENT_ACTION)
			|| io.query_event(IOEvent::MOUSETARGET_CURRENT_ACTION);
	if ((do_stopaction && !action_usage) || gs->key_down_state(SDLK_PERIOD)
			|| gs->mouse_downwheel()) {
		queue_portal_use(gs, this, queued_actions);
	}

// If we haven't done anything, rest
	if (queued_actions.empty()) {
		queued_actions.push_back(game_action(gs, this, GameAction::USE_REST));
	}

	ActionQueue only_passive_actions;

	for (int i = 0; i < queued_actions.size(); i++) {
		GameAction::action_t act = queued_actions[i].act;
		if (act == GameAction::MOVE || act == GameAction::USE_REST) {
			only_passive_actions.push_back(queued_actions[i]);
		}
	}

	GameNetConnection& net = gs->net_connection();
	if (net.is_connected()) {
		net_send_player_actions(net, gs->frame(),
				player_get_playernumber(gs, this), queued_actions);
	}

	int repeat = single_player ? 0 : settings.frame_action_repeat;
	for (int i = 1; i <= repeat; i++) {
		for (int j = 0; j < only_passive_actions.size(); j++) {
			only_passive_actions[j].frame = gs->frame() + i;
		}
		pde.action_queue.queue_actions_for_frame(only_passive_actions,
				gs->frame() + i);

		if (net.is_connected()) {
			net_send_player_actions(net, gs->frame() + i,
					player_get_playernumber(gs, this), only_passive_actions);
		}
	}

}
示例#12
0
void PlayerInst::enqueue_io_equipment_actions(GameState* gs,
		bool do_stopaction) {
	GameView& view = gs->view();
	bool mouse_within = gs->mouse_x() < gs->view().width;
	int rmx = view.x + gs->mouse_x(), rmy = view.y + gs->mouse_y();

	int level = gs->get_level()->id();
	int frame = gs->frame();
	bool item_used = false;
	IOController& io = gs->io_controller();

	Pos p(gs->mouse_x() + view.x, gs->mouse_y() + view.y);
	obj_id target = this->current_target;
	GameInst* targetted = gs->get_instance(target);
	if (targetted)
		p = Pos(targetted->x, targetted->y);

// We may have already used an item eg due to auto-use of items
	bool used_item = false;

//Item use
	for (int i = 0; i < 9 && !used_item; i++) {
		if (io.query_event(IOEvent(IOEvent::USE_ITEM_N, i))) {
			if (inventory().get(i).amount() > 0) {
				item_used = true;
				queued_actions.push_back(
						GameAction(id, GameAction::USE_ITEM, frame, level, i,
								p.x, p.y));
			}
		}
	}
	if (!used_item && gs->game_settings().autouse_health_potions
			&& core_stats().hp < AUTOUSE_HEALTH_POTION_THRESHOLD) {
		int item_slot = inventory().find_slot(
				get_item_by_name("Health Potion"));
		if (item_slot > -1) {
			queued_actions.push_back(
					game_action(gs, this, GameAction::USE_ITEM, item_slot));
			used_item = true;
		}
	}

//Item pickup
	GameInst* inst = NULL;
	if (cooldowns().can_pickup()
			&& gs->object_radius_test(this, &inst, 1, &item_colfilter)) {
		ItemInst* iteminst = (ItemInst*)inst;
		Item& item = iteminst->item_type();

		bool was_dropper = iteminst->last_held_by() == id;
		bool dropper_autopickup = iteminst->autopickup_held();

		bool autopickup = (item.is_normal_item() && !was_dropper
				&& !dropper_autopickup) || (was_dropper && dropper_autopickup);

		bool wieldable_projectile = projectile_should_autowield(equipment(),
				item, this->last_chosen_weaponclass);

		bool pickup_io = gs->key_down_state(SDLK_LSHIFT)
				|| gs->key_down_state(SDLK_RSHIFT);

		if (do_stopaction || wieldable_projectile || pickup_io || autopickup)
			queued_actions.push_back(
					GameAction(id, GameAction::PICKUP_ITEM, frame, level,
							iteminst->id));
	}
}