* @param x 中心生成位置x座標
* @param r_idx 生成モンスター種族
* @param mode 生成オプション
+ * @param summoner_m_idx モンスターの召喚による場合、召喚主のモンスターID
* @return 成功したらtrue
*/
-static bool place_monster_group(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode)
+static bool place_monster_group(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto *r_ptr = &monraces_info[r_idx];
auto total = randint1(10);
continue;
}
- if (place_monster_one(player_ptr, src_idx, my, mx, r_idx, mode)) {
+ if (place_monster_one(player_ptr, src_idx, my, mx, r_idx, mode, summoner_m_idx)) {
hack_y[hack_n] = my;
hack_x[hack_n] = mx;
hack_n++;
* @param x 生成地点x座標
* @param r_idx 生成するモンスターの種族ID
* @param mode 生成オプション
+ * @param summoner_m_idx モンスターの召喚による場合、召喚主のモンスターID
* @return 生成に成功したらtrue
* @details 護衛も一緒に生成する
*/
-bool place_specific_monster(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode)
+bool place_specific_monster(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto *r_ptr = &monraces_info[r_idx];
mode |= PM_KAGE;
}
- if (!place_monster_one(player_ptr, src_idx, y, x, r_idx, mode)) {
+ if (!place_monster_one(player_ptr, src_idx, y, x, r_idx, mode, summoner_m_idx)) {
return false;
}
if (!(mode & PM_ALLOW_GROUP)) {
const POSITION scatter_max = 40;
for (d = scatter_min; d <= scatter_max; d++) {
scatter(player_ptr, &ny, &nx, y, x, d, PROJECT_NONE);
- if (place_monster_one(player_ptr, place_monster_m_idx, ny, nx, reinforce_r_idx, mode)) {
+ if (place_monster_one(player_ptr, place_monster_m_idx, ny, nx, reinforce_r_idx, mode, summoner_m_idx)) {
break;
}
}
}
if (r_ptr->misc_flags.has(MonsterMiscType::HAS_FRIENDS)) {
- (void)place_monster_group(player_ptr, src_idx, y, x, r_idx, mode);
+ (void)place_monster_group(player_ptr, src_idx, y, x, r_idx, mode, summoner_m_idx);
}
if (r_ptr->misc_flags.has_not(MonsterMiscType::ESCORT)) {
break;
}
- (void)place_monster_one(player_ptr, place_monster_m_idx, ny, nx, z, mode);
+ (void)place_monster_one(player_ptr, place_monster_m_idx, ny, nx, z, mode, summoner_m_idx);
if (monraces_info[z].misc_flags.has(MonsterMiscType::HAS_FRIENDS) || r_ptr->misc_flags.has(MonsterMiscType::MORE_ESCORT)) {
- (void)place_monster_group(player_ptr, place_monster_m_idx, ny, nx, z, mode);
+ (void)place_monster_group(player_ptr, place_monster_m_idx, ny, nx, z, mode, summoner_m_idx);
}
}
#pragma once
#include "system/angband.h"
+#include <optional>
enum summon_type : int;
enum class MonsterRaceId : int16_t;
bool mon_scatter(PlayerType *player_ptr, MonsterRaceId r_idx, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION max_dist);
bool multiply_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool clone, BIT_FLAGS mode);
-bool place_specific_monster(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode);
+bool place_specific_monster(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode, std::optional<MONSTER_IDX> summoner_m_idx = std::nullopt);
bool place_random_monster(PlayerType *player_ptr, POSITION y, POSITION x, BIT_FLAGS mode);
bool alloc_horde(PlayerType *player_ptr, POSITION y, POSITION x, summon_specific_pf summon_specific);
bool alloc_guardian(PlayerType *player_ptr, bool def_val);
#include "system/player-type-definition.h"
/*!
- * @var summon_specific_who
- * @brief 召喚を行ったプレイヤーあるいはモンスターのIDを示すグローバル変数 / Hack -- the index of the summoning monster
- * @todo summon_specific_who グローバル変数の除去と関数引数への代替を行う
- */
-int summon_specific_who = -1;
-
-/*!
- * @var summon_unique_okay
- * @brief 召喚対象にユニークを含めるかを示すグローバル変数 / summoning unique enable
- * @todo summon_unique_okay グローバル変数の除去と関数引数への代替を行う
- */
-bool summon_unique_okay = false;
-
-/*!
* @brief モンスターが召喚の基本条件に合っているかをチェックする / Hack -- help decide if a monster race is "okay" to summon
* @param r_idx チェックするモンスター種族ID
+ * @param summon_who 召喚主のモンスター情報ID
+ * @param type 召喚種別
+ * @param is_unique_allowed ユニークモンスターを召喚対象に含めるかどうか
* @return 召喚対象にできるならばTRUE
*/
-static bool summon_specific_okay(PlayerType *player_ptr, MonsterRaceId r_idx)
+static bool summon_specific_okay(PlayerType *player_ptr, MonsterRaceId r_idx, MONSTER_IDX summon_who, summon_type type, bool is_unique_allowed)
{
auto *r_ptr = &monraces_info[r_idx];
if (!mon_hook_dungeon(player_ptr, r_idx)) {
}
auto &floor = *player_ptr->current_floor_ptr;
- if (summon_specific_who > 0) {
- auto *m_ptr = &floor.m_list[summon_specific_who];
+ if (summon_who > 0) {
+ auto *m_ptr = &floor.m_list[summon_who];
if (monster_has_hostile_align(player_ptr, m_ptr, 0, 0, r_ptr)) {
return false;
}
- } else if (summon_specific_who < 0) {
+ } else if (summon_who < 0) {
if (monster_has_hostile_align(player_ptr, nullptr, 10, -10, r_ptr) && !one_in_(std::abs(player_ptr->alignment) / 2 + 1)) {
return false;
}
}
- if (!summon_unique_okay && (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)))) {
+ if (!is_unique_allowed && (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL)))) {
return false;
}
- if (!summon_specific_type) {
+ if (type == SUMMON_NONE) {
return true;
}
const auto is_like_unique = r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || (r_ptr->population_flags.has(MonsterPopulationType::NAZGUL));
- if ((summon_specific_who < 0) && is_like_unique && monster_has_hostile_align(player_ptr, nullptr, 10, -10, r_ptr)) {
+ if ((summon_who < 0) && is_like_unique && monster_has_hostile_align(player_ptr, nullptr, 10, -10, r_ptr)) {
return false;
}
return true;
}
- if (summon_specific_who > 0) {
- auto *m_ptr = &floor.m_list[summon_specific_who];
- return check_summon_specific(player_ptr, m_ptr->r_idx, r_idx);
+ if (summon_who > 0) {
+ auto *m_ptr = &floor.m_list[summon_who];
+ return check_summon_specific(player_ptr, m_ptr->r_idx, r_idx, type);
} else {
- return check_summon_specific(player_ptr, MonsterRaceId::PLAYER, r_idx);
+ return check_summon_specific(player_ptr, MonsterRaceId::PLAYER, r_idx, type);
}
}
return false;
}
- summon_specific_who = src_idx;
- summon_specific_type = type;
- summon_unique_okay = (mode & PM_ALLOW_UNIQUE) != 0;
- get_mon_num_prep(player_ptr, summon_specific_okay, get_monster_hook2(player_ptr, y, x));
+ auto summon_specific_hook = [src_idx, type, is_unique_allowed = (mode & PM_ALLOW_UNIQUE) != 0](PlayerType *player_ptr, MonsterRaceId r_idx) {
+ return summon_specific_okay(player_ptr, r_idx, src_idx, type, is_unique_allowed);
+ };
+ get_mon_num_prep(player_ptr, std::move(summon_specific_hook), get_monster_hook2(player_ptr, y, x));
DEPTH dlev = get_dungeon_or_wilderness_level(player_ptr);
MonsterRaceId r_idx = get_mon_num(player_ptr, 0, (dlev + lev) / 2 + 5, mode);
if (!MonsterRace(r_idx).is_valid()) {
- summon_specific_type = SUMMON_NONE;
return false;
}
mode |= PM_NO_KAGE;
}
- if (!place_specific_monster(player_ptr, src_idx, y, x, r_idx, mode)) {
- summon_specific_type = SUMMON_NONE;
+ const auto summon_who = is_monster(src_idx) ? std::make_optional(src_idx) : std::nullopt;
+ if (!place_specific_monster(player_ptr, src_idx, y, x, r_idx, mode, summon_who)) {
return false;
}
- summon_specific_type = SUMMON_NONE;
-
bool notice = false;
if (!is_monster(src_idx)) {
notice = true;
#include "system/angband.h"
-extern int summon_specific_who;
-extern bool summon_unique_okay;
-
enum summon_type : int;
enum class MonsterRaceId : int16_t;
class PlayerType;
}
auto hook_pf = get_monster_hook(player_ptr);
- return (*hook_pf)(player_ptr, r_idx);
+ return hook_pf(player_ptr, r_idx);
}
/*!
* @param x 生成位置x座標
* @param r_idx 生成モンスター種族
* @param mode 生成オプション
+ * @param summoner_m_idx モンスターの召喚による場合、召喚主のモンスターID
* @return 成功したらtrue
*/
-bool place_monster_one(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode)
+bool place_monster_one(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto &floor = *player_ptr->current_floor_ptr;
auto *g_ptr = &floor.grid_array[y][x];
}
if (r_ptr->misc_flags.has(MonsterMiscType::CHAMELEON)) {
- choose_new_monster(player_ptr, g_ptr->m_idx, true, MonsterRace::empty_id());
+ choose_new_monster(player_ptr, g_ptr->m_idx, true, MonsterRace::empty_id(), summoner_m_idx);
r_ptr = &m_ptr->get_monrace();
m_ptr->mflag2.set(MonsterConstantFlagType::CHAMELEON);
if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && (!is_monster(src_idx))) {
#pragma once
#include "system/angband.h"
+#include <optional>
enum class MonsterRaceId : int16_t;
class PlayerType;
-bool place_monster_one(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode);
+bool place_monster_one(PlayerType *player_ptr, MONSTER_IDX src_idx, POSITION y, POSITION x, MonsterRaceId r_idx, BIT_FLAGS mode, std::optional<MONSTER_IDX> summoner_m_idx = std::nullopt);
* @param player_ptr プレイヤーへの参照ポインタ
* @brief カメレオンの王の変身対象となるモンスターかどうか判定する / Hack -- the index of the summoning monster
* @param r_idx モンスター種族ID
+ * @param summoner_m_idx モンスターの召喚による場合、召喚者のモンスターID
* @return 対象にできるならtrueを返す
*/
-static bool monster_hook_chameleon_lord(PlayerType *player_ptr, MonsterRaceId r_idx)
+static bool monster_hook_chameleon_lord(PlayerType *player_ptr, MonsterRaceId r_idx, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto *floor_ptr = player_ptr->current_floor_ptr;
auto *r_ptr = &monraces_info[r_idx];
if (monster_has_hostile_align(player_ptr, m_ptr, 0, 0, r_ptr)) {
return false;
}
- } else if (summon_specific_who > 0) {
- if (monster_has_hostile_align(player_ptr, &floor_ptr->m_list[summon_specific_who], 0, 0, r_ptr)) {
- return false;
- }
+ } else if (summoner_m_idx && monster_has_hostile_align(player_ptr, &floor_ptr->m_list[*summoner_m_idx], 0, 0, r_ptr)) {
+ return false;
}
return true;
/*!
* @brief カメレオンの変身対象となるモンスターかどうか判定する / Hack -- the index of the summoning monster
* @param r_idx モンスター種族ID
+ * @param summoner_m_idx モンスターの召喚による場合、召喚者のモンスターID
* @return 対象にできるならtrueを返す
* @todo グローバル変数対策の上 monster_hook.cへ移す。
*/
-static bool monster_hook_chameleon(PlayerType *player_ptr, MonsterRaceId r_idx)
+static bool monster_hook_chameleon(PlayerType *player_ptr, MonsterRaceId r_idx, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto *floor_ptr = player_ptr->current_floor_ptr;
auto *r_ptr = &monraces_info[r_idx];
if (old_r_ptr->kind_flags.has_none_of(alignment_mask)) {
return false;
}
- } else if (summon_specific_who > 0) {
- if (monster_has_hostile_align(player_ptr, &floor_ptr->m_list[summon_specific_who], 0, 0, r_ptr)) {
- return false;
- }
+ } else if (summoner_m_idx && monster_has_hostile_align(player_ptr, &floor_ptr->m_list[*summoner_m_idx], 0, 0, r_ptr)) {
+ return false;
}
auto hook_pf = get_monster_hook(player_ptr);
- return (*hook_pf)(player_ptr, r_idx);
+ return hook_pf(player_ptr, r_idx);
}
/*!
* @param m_idx 変身処理を受けるモンスター情報のID
* @param born 生成時の初変身先指定ならばtrue
* @param r_idx 旧モンスター種族のID
+ * @param summoner_m_idx モンスターの召喚による場合、召喚者のモンスターID
*/
-void choose_new_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool born, MonsterRaceId r_idx)
+void choose_new_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool born, MonsterRaceId r_idx, std::optional<MONSTER_IDX> summoner_m_idx)
{
auto *floor_ptr = player_ptr->current_floor_ptr;
auto *m_ptr = &floor_ptr->m_list[m_idx];
chameleon_change_m_idx = m_idx;
if (old_unique) {
- get_mon_num_prep(player_ptr, monster_hook_chameleon_lord, nullptr);
+ auto hook = [summoner_m_idx](PlayerType *player_ptr, MonsterRaceId r_idx) { return monster_hook_chameleon_lord(player_ptr, r_idx, summoner_m_idx); };
+ get_mon_num_prep(player_ptr, std::move(hook), nullptr);
} else {
- get_mon_num_prep(player_ptr, monster_hook_chameleon, nullptr);
+ auto hook = [summoner_m_idx](PlayerType *player_ptr, MonsterRaceId r_idx) { return monster_hook_chameleon(player_ptr, r_idx, summoner_m_idx); };
+ get_mon_num_prep(player_ptr, std::move(hook), nullptr);
}
if (old_unique) {
#pragma once
#include "system/angband.h"
+#include <optional>
enum class MonsterRaceId : int16_t;
class FloorType;
MONSTER_IDX m_pop(FloorType *floor_ptr);
MonsterRaceId get_mon_num(PlayerType *player_ptr, DEPTH min_level, DEPTH max_level, BIT_FLAGS mode);
-void choose_new_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool born, MonsterRaceId r_idx);
+void choose_new_monster(PlayerType *player_ptr, MONSTER_IDX m_idx, bool born, MonsterRaceId r_idx, std::optional<MONSTER_IDX> summoner_m_idx = std::nullopt);
byte get_mspeed(FloorType *player_ptr, MonsterRaceInfo *r_ptr);
int get_monster_crowd_number(FloorType *floor_ptr, MONSTER_IDX m_idx);
#pragma once
#include "system/angband.h"
+#include <functional>
enum class MonsterRaceId : int16_t;
class PlayerType;
-typedef bool (*monsterrace_hook_type)(PlayerType *, MonsterRaceId);
+using monsterrace_hook_type = std::function<bool(PlayerType *, MonsterRaceId)>;
extern MONSTER_IDX hack_m_idx;
extern MONSTER_IDX hack_m_idx_ii;
extern int chameleon_change_m_idx;
enum summon_type : int;
-extern summon_type summon_specific_type;
monsterrace_hook_type get_monster_hook(PlayerType *player_ptr);
monsterrace_hook_type get_monster_hook2(PlayerType *player_ptr, POSITION y, POSITION x);
* @return 召喚条件が一致するならtrue
* @details
*/
-bool check_summon_specific(PlayerType *player_ptr, MonsterRaceId summoner_idx, MonsterRaceId r_idx)
+bool check_summon_specific(PlayerType *player_ptr, MonsterRaceId summoner_idx, MonsterRaceId r_idx, summon_type type)
{
const auto &monrace = monraces_info[r_idx];
- switch (summon_specific_type) {
+ switch (type) {
case SUMMON_ANT:
return monrace.d_char == 'a';
case SUMMON_SPIDER:
#include "system/angband.h"
+enum summon_type : int;
enum class MonsterRaceId : int16_t;
class PlayerType;
-bool check_summon_specific(PlayerType *player_ptr, MonsterRaceId summoner_idx, MonsterRaceId r_idx);
+bool check_summon_specific(PlayerType *player_ptr, MonsterRaceId summoner_idx, MonsterRaceId r_idx, summon_type type);