Hengband
2.2.1
|
魔法による遠隔処理の実装 / Spell projection [詳解]
#include "angband.h"
#include "core.h"
#include "util.h"
#include "cmd-pet.h"
#include "cmd-dump.h"
#include "floor.h"
#include "trap.h"
#include "autopick.h"
#include "object-curse.h"
#include "player-damage.h"
#include "player-effects.h"
#include "player-race.h"
#include "player-class.h"
#include "monster.h"
#include "monster-status.h"
#include "monster-spell.h"
#include "spells.h"
#include "spells-status.h"
#include "spells-diceroll.h"
#include "spells-summon.h"
#include "monsterrace-hook.h"
#include "melee.h"
#include "world.h"
#include "mutation.h"
#include "rooms.h"
#include "artifact.h"
#include "avatar.h"
#include "player-status.h"
#include "player-move.h"
#include "realm-hex.h"
#include "realm-song.h"
#include "object-hook.h"
#include "object-broken.h"
#include "object-flavor.h"
#include "quest.h"
#include "term.h"
#include "grid.h"
#include "feature.h"
#include "view-mainwindow.h"
#include "dungeon.h"
関数 | |
static void | next_mirror (player_type *creature_ptr, POSITION *next_y, POSITION *next_x, POSITION cury, POSITION curx) |
配置した鏡リストの次を取得する / Get another mirror. [詳解] | |
static bool | project_f (floor_type *floor_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ) |
汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features [詳解] | |
static bool | project_o (MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ) |
汎用的なビーム/ボルト/ボール系によるアイテムオブジェクトへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. [詳解] | |
static bool | project_m (MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flg, bool see_s_msg) |
汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. [詳解] | |
static bool | project_p (MONSTER_IDX who, player_type *target_ptr, concptr who_name, int r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flg, int monspell) |
汎用的なビーム/ボルト/ボール系によるプレイヤーへの効果処理 / Helper function for "project()" below. [詳解] | |
POSITION | dist_to_line (POSITION y, POSITION x, POSITION y1, POSITION x1, POSITION y2, POSITION x2) |
bool | in_disintegration_range (POSITION y1, POSITION x1, POSITION y2, POSITION x2) |
void | breath_shape (u16b *path_g, int dist, int *pgrids, POSITION *gx, POSITION *gy, POSITION *gm, POSITION *pgm_rad, POSITION rad, POSITION y1, POSITION x1, POSITION y2, POSITION x2, EFFECT_ID typ) |
bool | project (MONSTER_IDX who, POSITION rad, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ, BIT_FLAGS flg, int monspell) |
汎用的なビーム/ボルト/ボール系処理のルーチン Generic "beam"/"bolt"/"ball" projection routine. [詳解] | |
bool | binding_field (player_type *caster_ptr, HIT_POINT dam) |
鏡魔法「封魔結界」の効果処理 [詳解] | |
void | seal_of_mirror (HIT_POINT dam) |
鏡魔法「鏡の封印」の効果処理 [詳解] | |
concptr | spell_category_name (OBJECT_TYPE_VALUE tval) |
領域魔法に応じて技能の名称を返す。 [詳解] | |
変数 | |
static int | rakubadam_m |
振り落とされた際のダメージ量 [詳解] | |
static int | rakubadam_p |
落馬した際のダメージ量 [詳解] | |
bool | sukekaku |
int | project_length = 0 |
投射の射程距離 [詳解] | |
int | cap_mon |
int | cap_mspeed |
HIT_POINT | cap_hp |
HIT_POINT | cap_maxhp |
STR_OFFSET | cap_nickname |
const magic_type | technic_info [NUM_TECHNIC][32] |
歌、剣術、呪術領域情報テーブル [詳解] | |
static int | project_m_n |
魔法効果範囲内にいるモンスターの数 [詳解] | |
static POSITION | project_m_x |
処理中のモンスターX座標 [詳解] | |
static POSITION | project_m_y |
処理中のモンスターY座標 [詳解] | |
static POSITION | monster_target_x |
モンスターの攻撃目標X座標 [詳解] | |
static POSITION | monster_target_y |
モンスターの攻撃目標Y座標 [詳解] | |
魔法による遠隔処理の実装 / Spell projection
bool binding_field | ( | player_type * | caster_ptr, |
HIT_POINT | dam | ||
) |
鏡魔法「封魔結界」の効果処理
dam | ダメージ量 |
void breath_shape | ( | u16b * | path_g, |
int | dist, | ||
int * | pgrids, | ||
POSITION * | gx, | ||
POSITION * | gy, | ||
POSITION * | gm, | ||
POSITION * | pgm_rad, | ||
POSITION | rad, | ||
POSITION | y1, | ||
POSITION | x1, | ||
POSITION | y2, | ||
POSITION | x2, | ||
EFFECT_ID | typ | ||
) |
POSITION dist_to_line | ( | POSITION | y, |
POSITION | x, | ||
POSITION | y1, | ||
POSITION | x1, | ||
POSITION | y2, | ||
POSITION | x2 | ||
) |
|
static |
配置した鏡リストの次を取得する / Get another mirror.
for SEEKER
next_y | 次の鏡のy座標を返す参照ポインタ |
next_x | 次の鏡のx座標を返す参照ポインタ |
cury | 現在の鏡のy座標 |
curx | 現在の鏡のx座標 |
bool project | ( | MONSTER_IDX | who, |
POSITION | rad, | ||
POSITION | y, | ||
POSITION | x, | ||
HIT_POINT | dam, | ||
EFFECT_ID | typ, | ||
BIT_FLAGS | flg, | ||
int | monspell | ||
) |
汎用的なビーム/ボルト/ボール系処理のルーチン Generic "beam"/"bolt"/"ball" projection routine.
who | 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") |
rad | 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) |
y | 目標Y座標 / Target y location (or location to travel "towards") |
x | 目標X座標 / Target x location (or location to travel "towards") |
dam | 基本威力 / Base damage roll to apply to affected monsters (or player) |
typ | 効果属性 / Type of damage to apply to monsters (and objects) |
flg | 効果フラグ / Extra bit flags (see PROJECT_xxxx) |
monspell | 効果元のモンスター魔法ID |
Allows a monster (or player) to project a beam/bolt/ball of a given kind towards a given location (optionally passing over the heads of interposing monsters), and have it do a given amount of damage to the monsters (and optionally objects) within the given radius of the final location.
A "bolt" travels from source to target and affects only the target grid. A "beam" travels from source to target, affecting all grids passed through. A "ball" travels from source to the target, exploding at the target, and affecting everything within the given radius of the target location.
Traditionally, a "bolt" does not affect anything on the ground, and does not pass over the heads of interposing monsters, much like a traditional missile, and will "stop" abruptly at the "target" even if no monster is positioned there, while a "ball", on the other hand, passes over the heads of monsters between the source and target, and affects everything except the source monster which lies within the final radius, while a "beam" affects every monster between the source and target, except for the casting monster (or player), and rarely affects things on the ground.
Two special flags allow us to use this function in special ways, the "PROJECT_HIDE" flag allows us to perform "invisible" projections, while the "PROJECT_JUMP" flag allows us to affect a specific grid, without actually projecting from the source monster (or player).
The player will only get "experience" for monsters killed by himself Unique monsters can only be destroyed by attacks from the player
Only 256 grids can be affected per projection, limiting the effective "radius" of standard ball attacks to nine units (diameter nineteen).
One can project in a given "direction" by combining PROJECT_THRU with small offsets to the initial location (see "line_spell()"), or by calculating "virtual targets" far away from the player.
One can also use PROJECT_THRU to send a beam/bolt along an angled path, continuing until it actually hits somethings (useful for "stone to mud").
Bolts and Beams explode INSIDE walls, so that they can destroy doors.
Balls must explode BEFORE hitting walls, or they would affect monsters on both sides of a wall. Some bug reports indicate that this is still happening in 2.7.8 for Windows, though it appears to be impossible.
We "pre-calculate" the blast area only in part for efficiency. More importantly, this lets us do "explosions" from the "inside" out. This results in a more logical distribution of "blast" treasure. It also produces a better (in my opinion) animation of the explosion. It could be (but is not) used to have the treasure dropped by monsters in the middle of the explosion fall "outwards", and then be damaged by the blast as it spreads outwards towards the treasure drop location.
Walls and doors are included in the blast area, so that they can be "burned" or "melted" in later versions.
This algorithm is intended to maximize simplicity, not necessarily efficiency, since this function is not a bottleneck in the code.
We apply the blast effect from ground zero outwards, in several passes, first affecting features, then objects, then monsters, then the player. This allows walls to be removed before checking the object or monster in the wall, and protects objects which are dropped by monsters killed in the blast, and allows the player to see all affects before he is killed or teleported away. The semantics of this method are open to various interpretations, but they seem to work well in practice.
We process the blast area from ground-zero outwards to allow for better distribution of treasure dropped by monsters, and because it provides a pleasing visual effect at low cost.
Note that the damage done by "ball" explosions decreases with distance. This decrease is rapid, grids at radius "dist" take "1/dist" damage.
Notice the "napalm" effect of "beam" weapons. First they "project" to the target, and then the damage "flows" along this beam of destruction. The damage at every grid is the same as at the "center" of a "ball" explosion, since the "beam" grids are treated as if they ARE at the center of a "ball" explosion.
Currently, specifying "beam" plus "ball" means that locations which are covered by the initial "beam", and also covered by the final "ball", except for the final grid (the epicenter of the ball), will be "hit twice", once by the initial beam, and once by the exploding ball. For the grid right next to the epicenter, this results in 150% damage being done. The center does not have this problem, for the same reason the final grid in a "beam" plus "bolt" does not -- it is explicitly removed. Simply removing "beam" grids which are covered by the "ball" will NOT work, as then they will receive LESS damage than they should. Do not combine "beam" with "ball".
The array "gy[],gx[]" with current size "grids" is used to hold the collected locations of all grids in the "blast area" plus "beam path".
Note the rather complex usage of the "gm[]" array. First, gm[0] is always zero. Second, for N>1, gm[N] is always the index (in gy[],gx[]) of the first blast grid (see above) with radius "N" from the blast center. Note that only the first gm[1] grids in the blast area thus take full damage. Also, note that gm[rad+1] is always equal to "grids", which is the total number of blast grids.
Note that once the projection is complete, (y2,x2) holds the final location of bolts/beams, and the "epicenter" of balls.
Note also that "rad" specifies the "inclusive" radius of projection blast, so that a "rad" of "one" actually covers 5 or 9 grids, depending on the implementation of the "distance" function. Also, a bolt can be properly viewed as a "ball" with a "rad" of "zero".
Note that if no "target" is reached before the beam/bolt/ball travels the maximum distance allowed (MAX_RANGE), no "blast" will be induced. This may be relevant even for bolts, since they have a "1x1" mini-blast.
Note that for consistency, we "pretend" that the bolt actually takes "time" to move from point A to point B, even if the player cannot see part of the projection path. Note that in general, the player will *always* see part of the path, since it either starts at the player or ends on the player.
Hack -- we assume that every "projection" is "self-illuminating".
Hack -- when only a single monster is affected, we automatically track (and recall) that monster, unless "PROJECT_JUMP" is used.
Note that all projections now "explode" at their final destination, even if they were being projected at a more distant destination. This means that "ball" spells will *always* explode.
Note that we must call "handle_stuff()" after affecting terrain features in the blast radius, in case the "illumination" of the grid was changed, and "update_view()" and "update_monsters()" need to be called.
|
static |
汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features
who | 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") |
r | 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) |
y | 目標Y座標 / Target y location (or location to travel "towards") |
x | 目標X座標 / Target x location (or location to travel "towards") |
dam | 基本威力 / Base damage roll to apply to affected monsters (or player) |
typ | 効果属性 / Type of damage to apply to monsters (and objects) |
We are called both for "beam" effects and "ball" effects.
The "r" parameter is the "distance from ground zero".
Note that we determine if the player can "see" anything that happens by taking into account: blindness, line-of-sight, and illumination.
We return "TRUE" if the effect of the projection is "obvious".
We also "see" grids which are "memorized", probably a hack
Perhaps we should affect doors?
|
static |
汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
who | 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") |
r | 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) |
y | 目標Y座標 / Target y location (or location to travel "towards") |
x | 目標X座標 / Target x location (or location to travel "towards") |
dam | 基本威力 / Base damage roll to apply to affected monsters (or player) |
typ | 効果属性 / Type of damage to apply to monsters (and objects) |
flg | 効果フラグ |
see_s_msg | TRUEならばメッセージを表示する |
This routine takes a "source monster" (by index) which is mostly used to determine if the player is causing the damage, and a "radius" (see below), which is used to decrease the power of explosions with distance, and a location, via integers which are modified by certain types of attacks (polymorph and teleport being the obvious ones), a default damage, which is modified as needed based on various properties, and finally a "damage type" (see below).
Note that this routine can handle "no damage" attacks (like teleport) by taking a "zero" damage, and can even take "parameters" to attacks (like confuse) by accepting a "damage", using it to calculate the effect, and then setting the damage to zero. Note that the "damage" parameter is divided by the radius, so monsters not at the "epicenter" will not take as much damage (or whatever)...
Note that "polymorph" is dangerous, since a failure in "place_monster()"' may result in a dereference of an invalid pointer.
Various messages are produced, and damage is applied.
Just "casting" a substance (i.e. plasma) does not make you immune, you must actually be "made" of that substance, or "breathe" big balls of it. We assume that "Plasma" monsters, and "Plasma" breathers, are immune to plasma. We assume "Nether" is an evil, necromantic force, so it doesn't hurt undead, and hurts evil less. If can breath nether, then it resists it as well.
Damage reductions use the following formulas: Note that "dam = dam * 6 / (randint1(6) + 6);" gives avg damage of .655, ranging from .858 to .500 Note that "dam = dam * 5 / (randint1(6) + 6);" gives avg damage of .544, ranging from .714 to .417 Note that "dam = dam * 4 / (randint1(6) + 6);" gives avg damage of .444, ranging from .556 to .333 Note that "dam = dam * 3 / (randint1(6) + 6);" gives avg damage of .327, ranging from .427 to .250 Note that "dam = dam * 2 / (randint1(6) + 6);" gives something simple.
In this function, "result" messages are postponed until the end, where the "note" string is appended to the monster name, if not NULL. So, to make a spell have "no effect" just set "note" to NULL. You should also set "notice" to FALSE, or the player will learn what the spell does.
We attempt to return "TRUE" if the player saw anything "useful" happen. "flg" was added.
|
static |
汎用的なビーム/ボルト/ボール系によるアイテムオブジェクトへの効果処理 / Handle a beam/bolt/ball causing damage to a monster.
who | 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") |
r | 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) |
y | 目標Y座標 / Target y location (or location to travel "towards") |
x | 目標X座標 / Target x location (or location to travel "towards") |
dam | 基本威力 / Base damage roll to apply to affected monsters (or player) |
typ | 効果属性 / Type of damage to apply to monsters (and objects) |
We are called from "project()" to "damage" objects
We are called both for "beam" effects and "ball" effects.
Perhaps we should only SOMETIMES damage things on the ground.
The "r" parameter is the "distance from ground zero".
Note that we determine if the player can "see" anything that happens by taking into account: blindness, line-of-sight, and illumination.
We also "see" grids which are "memorized", probably a hack
We return "TRUE" if the effect of the projection is "obvious".
|
static |
汎用的なビーム/ボルト/ボール系によるプレイヤーへの効果処理 / Helper function for "project()" below.
who | 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player") |
who_name | 効果を起こしたモンスターの名前 |
r | 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball) |
y | 目標Y座標 / Target y location (or location to travel "towards") |
x | 目標X座標 / Target x location (or location to travel "towards") |
dam | 基本威力 / Base damage roll to apply to affected monsters (or player) |
typ | 効果属性 / Type of damage to apply to monsters (and objects) |
flg | 効果フラグ |
monspell | 効果元のモンスター魔法ID |
Handle a beam/bolt/ball causing damage to the player. This routine takes a "source monster" (by index), a "distance", a default "damage", and a "damage type". See "project_m()" above. If "rad" is non-zero, then the blast was centered elsewhere, and the damage is reduced (see "project_m()" above). This can happen if a monster breathes at the player and hits a wall instead. NOTE (Zangband): 'Bolt' attacks can be reflected back, so we need to know if this is actually a ball or a bolt spell We return "TRUE" if any "obvious" effects were observed. XXX XXX Actually, we just assume that the effects were obvious, for historical reasons.
void seal_of_mirror | ( | HIT_POINT | dam | ) |
鏡魔法「鏡の封印」の効果処理
dam | ダメージ量 |
concptr spell_category_name | ( | OBJECT_TYPE_VALUE | tval | ) |
領域魔法に応じて技能の名称を返す。
tval | 魔法書のtval |
HIT_POINT cap_hp |
HIT_POINT cap_maxhp |
int cap_mon |
int cap_mspeed |
STR_OFFSET cap_nickname |
|
static |
モンスターの攻撃目標X座標
|
static |
モンスターの攻撃目標Y座標
int project_length = 0 |
投射の射程距離
|
static |
魔法効果範囲内にいるモンスターの数
|
static |
処理中のモンスターX座標
|
static |
処理中のモンスターY座標
|
static |
振り落とされた際のダメージ量
|
static |
落馬した際のダメージ量
bool sukekaku |
const magic_type technic_info[NUM_TECHNIC][32] |
歌、剣術、呪術領域情報テーブル