魔法による遠隔処理の実装 / Spell projection [詳細]
#include "angband.h"
マクロ定義 | |
#define | HURT_CHANCE 16 |
属性攻撃を受けた際に能力値低下を起こす確率(1/X) / 1/x chance of reducing stats (for elemental attacks) [詳細] | |
関数 | |
static void | next_mirror (int *next_y, int *next_x, int cury, int curx) |
配置した鏡リストの次を取得する / Get another mirror. [詳細] | |
static byte | mh_attr (int max) |
万色表現用にランダムな色を選択する関数 / Get a legal "multi-hued" color for drawing "spells" [詳細] | |
static byte | spell_color (int type) |
魔法属性に応じたエフェクトの色を返す / Return a color to use for the bolt/ball spells [詳細] | |
u16b | bolt_pict (int y, int x, int ny, int nx, int typ) |
始点から終点にかけた方向毎にボルトのキャラクタを返す / Find the attr/char pair to use for a spell effect [詳細] | |
sint | project_path (u16b *gp, int range, int y1, int x1, int y2, int x2, int flg) |
始点から終点への経路を返す / Determine the path taken by a projection. [詳細] | |
static bool | project_f (int who, int r, int y, int x, int dam, int typ) |
汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features [詳細] | |
static bool | project_o (int who, int r, int y, int x, int dam, int typ) |
汎用的なビーム/ボルト/ボール系によるアイテムオブジェクトへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. [詳細] | |
static bool | project_m (int who, int r, int y, int x, int dam, int typ, int flg, bool see_s_msg) |
汎用的なビーム/ボルト/ボール系によるモンスターへの効果処理 / Handle a beam/bolt/ball causing damage to a monster. [詳細] | |
static bool | project_p (int who, cptr who_name, int r, int y, int x, int dam, int typ, int flg, int monspell) |
汎用的なビーム/ボルト/ボール系によるプレイヤーへの効果処理 / Helper function for "project()" below. [詳細] | |
int | dist_to_line (int y, int x, int y1, int x1, int y2, int x2) |
bool | in_disintegration_range (int y1, int x1, int y2, int x2) |
void | breath_shape (u16b *path_g, int dist, int *pgrids, byte *gx, byte *gy, byte *gm, int *pgm_rad, int rad, int y1, int x1, int y2, int x2, int typ) |
bool | project (int who, int rad, int y, int x, int dam, int typ, int flg, int monspell) |
汎用的なビーム/ボルト/ボール系処理のルーチン Generic "beam"/"bolt"/"ball" projection routine. [詳細] | |
bool | binding_field (int dam) |
鏡魔法「封魔結界」の効果処理 [詳細] | |
void | seal_of_mirror (int dam) |
鏡魔法「鏡の封印」の効果処理 [詳細] | |
変数 | |
static int | rakubadam_m |
振り落とされた際のダメージ量 [詳細] | |
static int | rakubadam_p |
落馬した際のダメージ量 [詳細] | |
int | project_length = 0 |
投射の射程距離 [詳細] | |
static int | project_m_n |
魔法効果範囲内にいるモンスターの数 [詳細] | |
static int | project_m_x |
処理中のモンスターX座標 [詳細] | |
static int | project_m_y |
処理中のモンスターY座標 [詳細] | |
static s16b | monster_target_x |
モンスターの攻撃目標X座標 [詳細] | |
static s16b | monster_target_y |
モンスターの攻撃目標Y座標 [詳細] | |
魔法による遠隔処理の実装 / Spell projection
#define HURT_CHANCE 16 |
属性攻撃を受けた際に能力値低下を起こす確率(1/X) / 1/x chance of reducing stats (for elemental attacks)
bool binding_field | ( | int | dam | ) |
鏡魔法「封魔結界」の効果処理
dam | ダメージ量 |
u16b bolt_pict | ( | int | y, |
int | x, | ||
int | ny, | ||
int | nx, | ||
int | typ | ||
) |
始点から終点にかけた方向毎にボルトのキャラクタを返す / Find the attr/char pair to use for a spell effect
y | 始点Y座標 |
x | 始点X座標 |
ny | 終点Y座標 |
nx | 終点X座標 |
typ | 魔法の効果属性 |
It is moving (or has moved) from (x,y) to (nx,ny). If the distance is not "one", we (may) return "*".
void breath_shape | ( | u16b * | path_g, |
int | dist, | ||
int * | pgrids, | ||
byte * | gx, | ||
byte * | gy, | ||
byte * | gm, | ||
int * | pgm_rad, | ||
int | rad, | ||
int | y1, | ||
int | x1, | ||
int | y2, | ||
int | x2, | ||
int | typ | ||
) |
int dist_to_line | ( | int | y, |
int | x, | ||
int | y1, | ||
int | x1, | ||
int | y2, | ||
int | x2 | ||
) |
bool in_disintegration_range | ( | int | y1, |
int | x1, | ||
int | y2, | ||
int | x2 | ||
) |
|
static |
万色表現用にランダムな色を選択する関数 / Get a legal "multi-hued" color for drawing "spells"
max | 色IDの最大値 |
|
static |
配置した鏡リストの次を取得する / Get another mirror.
for SEEKER
next_y | 次の鏡のy座標を返す参照ポインタ |
next_x | 次の鏡のx座標を返す参照ポインタ |
cury | 現在の鏡のy座標 |
curx | 現在の鏡のx座標 |
bool project | ( | int | who, |
int | rad, | ||
int | y, | ||
int | x, | ||
int | dam, | ||
int | typ, | ||
int | 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 in "defines.h") |
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".
XXX XXX XXX We also "see" grids which are "memorized", probably a hack
XXX XXX XXX 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. XXX XXX XXX
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.
XXX XXX XXX 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.
始点から終点への経路を返す / Determine the path taken by a projection.
gp | 経路座標リストを返す参照ポインタ |
range | 距離 |
y1 | 始点Y座標 |
x1 | 始点X座標 |
y2 | 終点Y座標 |
x2 | 終点X座標 |
flg | フラグID |
The projection will always start from the grid (y1,x1), and will travel towards the grid (y2,x2), touching one grid per unit of distance along the major axis, and stopping when it enters the destination grid or a wall grid, or has travelled the maximum legal distance of "range".
Note that "distance" in this function (as in the "update_view()" code) is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player actually has an "octagon of projection" not a "circle of projection".
The path grids are saved into the grid array pointed to by "gp", and there should be room for at least "range" grids in "gp". Note that due to the way in which distance is calculated, this function normally uses fewer than "range" grids for the projection path, so the result of this function should never be compared directly to "range". Note that the initial grid (y1,x1) is never saved into the grid array, not even if the initial grid is also the final grid. XXX XXX XXX
The "flg" flags can be used to modify the behavior of this function.
In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same semantics as they do for the "project" function, namely, that the path will stop as soon as it hits a monster, or that the path will continue through the destination grid, respectively.
The "PROJECT_JUMP" flag, which for the "project()" function means to start at a special grid (which makes no sense in this function), means that the path should be "angled" slightly if needed to avoid any wall grids, allowing the player to "target" any grid which is in "view". This flag is non-trivial and has not yet been implemented, but could perhaps make use of the "vinfo" array (above). XXX XXX XXX
This function returns the number of grids (if any) in the path. This function will return zero if and only if (y1,x1) and (y2,x2) are equal.
This algorithm is similar to, but slightly different from, the one used by "update_view_los()", and very different from the one used by "los()".
void seal_of_mirror | ( | int | dam | ) |
鏡魔法「鏡の封印」の効果処理
dam | ダメージ量 |
|
static |
魔法属性に応じたエフェクトの色を返す / Return a color to use for the bolt/ball spells
type | 魔法属性 |
|
static |
モンスターの攻撃目標X座標
|
static |
モンスターの攻撃目標Y座標
int project_length = 0 |
投射の射程距離
|
static |
魔法効果範囲内にいるモンスターの数
|
static |
処理中のモンスターX座標
|
static |
処理中のモンスターY座標
|
static |
振り落とされた際のダメージ量
|
static |
落馬した際のダメージ量