Angband
|
projection and helpers More...
Go to the source code of this file.
Macros | |
#define | ELEM(a, b, c, d, e, f, g, col) GF_##a, |
#define | PROJ_ENV(a, col) GF_##a, |
#define | PROJ_MON(a, obv) GF_##a, |
#define | PROJECT_NONE 0x000 |
NONE: No flags JUMP: Jump directly to the target location without following a path BEAM: Work as a beam weapon (affect every grid passed through) THRU: May continue through the target (used for bolts and beams) STOP: Stop as soon as we hit a monster (used for bolts) GRID: May affect terrain in the blast area in some way ITEM: May affect objects in the blast area in some way KILL: May affect monsters in the blast area in some way HIDE: Disable visual feedback from projection AWARE: Effects are already obvious to the player SAFE: Doesn't affect monsters of the same race as the caster ARC: Projection is a sector of circle radiating from the caster PLAY: May affect the player. | |
#define | PROJECT_JUMP 0x001 |
#define | PROJECT_BEAM 0x002 |
#define | PROJECT_THRU 0x004 |
#define | PROJECT_STOP 0x008 |
#define | PROJECT_GRID 0x010 |
#define | PROJECT_ITEM 0x020 |
#define | PROJECT_KILL 0x040 |
#define | PROJECT_HIDE 0x080 |
#define | PROJECT_AWARE 0x100 |
#define | PROJECT_SAFE 0x200 |
#define | PROJECT_ARC 0x400 |
#define | PROJECT_PLAY 0x800 |
Enumerations | |
enum | { GF_MAX } |
Spell types used by project(), and related functions. More... | |
enum | { BOLT_NO_MOTION, BOLT_0, BOLT_45, BOLT_90, BOLT_135, BOLT_MAX } |
Bolt motion (used in prefs.c, project.c) More... |
Functions | |
bool | project_f (int who, int r, int y, int x, int dam, int typ) |
Called from project() to affect terrain features. | |
int | inven_damage (struct player *p, int type, int cperc) |
Destroys a type of item on a given percent chance. | |
bool | project_o (int who, int r, int y, int x, int dam, int typ) |
Called from project() to affect objects. | |
bool | project_m (int who, int r, int y, int x, int dam, int typ, int flg) |
Called from project() to affect monsters. | |
int | adjust_dam (struct player *p, int type, int dam, aspect dam_aspect, int resist) |
Adjust damage according to resistance or vulnerability. | |
bool | project_p (int who, int r, int y, int x, int dam, int typ) |
Called from project() to affect the player. | |
int | project_path (struct loc *gp, int range, int y1, int x1, int y2, int x2, int flg) |
Determine the path taken by a projection. | |
bool | projectable (struct chunk *c, int y1, int x1, int y2, int x2, int flg) |
Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive at the final destination, assuming that no monster gets in the way, using the project_path() function to check the projection path. | |
bool | gf_force_obvious (int type) |
int | gf_color (int type) |
int | gf_num (int type) |
random_value | gf_denom (int type) |
const char * | gf_desc (int type) |
int | gf_name_to_idx (const char *name) |
const char * | gf_idx_to_name (int type) |
bool | project (int who, int rad, int y, int x, int dam, int typ, int flg, int degrees_of_arc, byte diameter_of_source) |
The main project() function and its helpers |
Variables | |
int | project_m_n |
int | project_m_x |
int | project_m_y |
byte | gf_to_attr [GF_MAX][BOLT_MAX] |
wchar_t | gf_to_char [GF_MAX][BOLT_MAX] |
projection and helpers
#define ELEM | ( | a, | |
b, | |||
c, | |||
d, | |||
e, | |||
f, | |||
g, | |||
col | |||
) | GF_##a, |
#define PROJ_ENV | ( | a, | |
col | |||
) | GF_##a, |
#define PROJ_MON | ( | a, | |
obv | |||
) | GF_##a, |
#define PROJECT_ARC 0x400 |
Referenced by project().
#define PROJECT_AWARE 0x100 |
Referenced by effect_handler_BOLT_AWARE(), effect_handler_PROJECT_LOS(), project_m(), and project_touch().
#define PROJECT_BEAM 0x002 |
Referenced by effect_handler_ALTER(), effect_handler_BEAM(), effect_handler_LINE(), effect_handler_STAR(), and project().
#define PROJECT_GRID 0x010 |
#define PROJECT_HIDE 0x080 |
Referenced by effect_handler_PROJECT_LOS(), project(), and project_touch().
#define PROJECT_ITEM 0x020 |
#define PROJECT_JUMP 0x001 |
Referenced by effect_handler_PROJECT_LOS(), and project().
#define PROJECT_KILL 0x040 |
Referenced by effect_handler_BALL(), effect_handler_BEAM(), effect_handler_BIZARRE(), effect_handler_BOLT(), effect_handler_BOLT_AWARE(), effect_handler_BREATH(), effect_handler_DARKEN_AREA(), effect_handler_LIGHT_AREA(), effect_handler_LINE(), effect_handler_PROJECT_LOS(), effect_handler_STAR(), effect_handler_STAR_BALL(), effect_handler_SWARM(), project(), and project_touch().
#define PROJECT_NONE 0x000 |
NONE: No flags JUMP: Jump directly to the target location without following a path BEAM: Work as a beam weapon (affect every grid passed through) THRU: May continue through the target (used for bolts and beams) STOP: Stop as soon as we hit a monster (used for bolts) GRID: May affect terrain in the blast area in some way ITEM: May affect objects in the blast area in some way KILL: May affect monsters in the blast area in some way HIDE: Disable visual feedback from projection AWARE: Effects are already obvious to the player SAFE: Doesn't affect monsters of the same race as the caster ARC: Projection is a sector of circle radiating from the caster PLAY: May affect the player.
Referenced by make_attack_spell(), monster_list_collect(), near_permwall(), and target_able().
#define PROJECT_PLAY 0x800 |
Referenced by effect_handler_BALL(), effect_handler_BREATH(), project(), and project_aimed().
#define PROJECT_SAFE 0x200 |
Referenced by project_m().
#define PROJECT_STOP 0x008 |
#define PROJECT_THRU 0x004 |
Referenced by effect_handler_BIZARRE(), effect_handler_SWARM(), project(), project_aimed(), project_path(), and target_set_interactive().
anonymous enum |
Spell types used by project(), and related functions.
anonymous enum |
Bolt motion (used in prefs.c, project.c)
Adjust damage according to resistance or vulnerability.
p | is the player |
type | is the attack type we are checking. |
dam | is the unadjusted damage. |
dam_aspect | is the calc we want (min, avg, max, random). |
resist | is the degree of resistance (-1 = vuln, 3 = immune). |
References AVERAGE, player_state::el_info, equip_notice_element(), EXTREMIFY, gf_denom(), gf_num(), i, MAXIMISE, MINIMISE, minus_ac(), player::race, randcalc(), RANDOMISE, element_info::res_level, player::state, and type.
Referenced by best_spell_power(), effect_handler_TRAP_SPOT_ACID(), effect_handler_TRAP_SPOT_FIRE(), melee_effect_elemental(), and project_p().
References gf_type::color, COLOUR_WHITE, GF_MAX, gf_table, and type.
Referenced by bolt_pict(), and gf_display().
random_value gf_denom | ( | int | type | ) |
References gf_type::denom, GF_MAX, gf_table, and type.
Referenced by adjust_dam().
References gf_type::desc, GF_MAX, gf_table, and type.
Referenced by project_p().
References FALSE, gf_type::force_obvious, GF_MAX, gf_table, and type.
Referenced by project_m().
References GF_MAX, gf_name_list, and type.
Referenced by gf_display().
References gf_name_list, i, and my_stricmp().
Referenced by effect_param(), and parse_prefs_gf().
References GF_MAX, gf_table, gf_type::num, and type.
Referenced by adjust_dam().
Destroys a type of item on a given percent chance.
The chance 'cperc' is in hundredths of a percent (1-in-10000) Note that missiles are no longer necessarily all destroyed
Returns number of items destroyed.
References object::artifact, player::body, object::el_info, EL_INFO_HATES, EL_INFO_IGNORE, FALSE, element_info::flags, player::gear, gear_object_for_use(), gear_to_label(), msgt(), object::next, object::number, object_delete(), object_desc(), object_is_equipped(), ODESC_BASE, PR_EQUIP, PU_BONUS, randint0, player_upkeep::redraw, reduce_charges(), object::to_a, object::to_d, object::to_h, TRUE, tval_is_ammo(), tval_is_armor(), tval_is_rod(), tval_is_weapon(), player_upkeep::update, and player::upkeep.
Referenced by effect_handler_TRAP_SPOT_ACID(), effect_handler_TRAP_SPOT_FIRE(), melee_effect_elemental(), project_player_handler_ACID(), project_player_handler_COLD(), project_player_handler_ELEC(), project_player_handler_FIRE(), and project_player_handler_ICE().
bool project | ( | int | who, |
int | rad, | ||
int | y, | ||
int | x, | ||
int | dam, | ||
int | typ, | ||
int | flg, | ||
int | degrees_of_arc, | ||
byte | diameter_of_source | ||
) |
Generic "beam"/"bolt"/"ball" projection routine. -BEN-, some changes by -LM-
who,: | Index of "source" monster (negative for the character) |
rad,: | Radius of explosion (0 = beam/bolt, 1 to 20 = ball), or maximum length of arc from the source. |
y | |
x,: | Target location (or location to travel towards) |
dam,: | Base damage to apply to monsters, terrain, objects, or player |
typ,: | Type of projection (fire, frost, dispel demons etc.) |
flg,: | Extra bit flags that control projection behavior |
degrees_of_arc,: | How wide an arc spell is (in degrees). |
diameter_of_source,: | how wide the source diameter is. |
At present, there are five major types of projections:
Point-effect projection: (no PROJECT_BEAM flag, radius of zero, and either jumps directly to target or has a single source and target grid) A point-effect projection has no line of projection, and only affects one grid. It is used for most area-effect spells (like dispel evil) and pinpoint strikes like the monster Holding prayer.
Bolt: (no PROJECT_BEAM flag, radius of zero, has to travel from source to target) A bolt travels from source to target and affects only the final grid in its projection path. If given the PROJECT_STOP flag, it is stopped by any monster or character in its path (at present, all bolts use this flag).
Beam: (PROJECT_BEAM) A beam travels from source to target, affecting all grids passed through with full damage. It is never stopped by monsters in its path. Beams may never be combined with any other projection type.
Ball: (positive radius, unless the PROJECT_ARC flag is set) A ball travels from source towards the target, and always explodes. Unless specified, it does not affect wall grids, but otherwise affects any grids in LOS from the center of the explosion. If used with a direction, a ball will explode on the first occupied grid in its path. If given a target, it will explode on that target. If a wall is in the way, it will explode against the wall. If a ball reaches z_info->max_range without hitting anything or reaching its target, it will explode at that point.
Arc: (positive radius, with the PROJECT_ARC flag set) An arc is a portion of a source-centered ball that explodes outwards towards the target grid. Like a ball, it affects all non-wall grids in LOS of the source in the explosion area. The width of arc spells is con- trolled by degrees_of_arc. An arc is created by rejecting all grids that form the endpoints of lines whose angular difference (in degrees) from the centerline of the arc is greater than one-half the input "degrees_of_arc". See the table "get_ angle_to_grid" in "util.c" for more information. Note: An arc with a value for degrees_of_arc of zero is actually a beam of defined length.
Projections that effect all monsters in LOS are handled through the use of the PROJECT_LOS effect, which applies a single-grid projection to individual monsters. Projections that light up rooms or affect all monsters on the level are more efficiently handled through special functions.
Variations:
PROJECT_STOP forces a path of projection to stop at the first occupied grid it hits. This is used with bolts, and also by ball spells travelling in a specific direction rather than towards a target.
PROJECT_THRU allows a path of projection towards a target to continue past that target. It also allows a spell to affect wall grids adjacent to a grid in LOS of the center of the explosion.
PROJECT_JUMP allows a projection to immediately set the source of the pro- jection to the target. This is used for all area effect spells (like dispel evil), and can also be used for bombardments.
PROJECT_HIDE erases all graphical effects, making the projection invisible.
PROJECT_GRID allows projections to affect terrain features.
PROJECT_ITEM allows projections to affect objects on the ground.
PROJECT_KILL allows projections to affect monsters.
PROJECT_PLAY allows projections to affect the player.
degrees_of_arc controls the width of arc spells. With a value for degrees_of_arc of zero, arcs act like beams of defined length.
diameter_of_source controls how quickly explosions lose strength with dis- tance from the target. Most ball spells have a source diameter of 10, which means that they do 1/2 damage at range 1, 1/3 damage at range 2, and so on. Caster-centered balls usually have a source diameter of 20, which allows them to do full damage to all adjacent grids. Arcs have source diameters ranging up to 20, which allows the spell designer to fine-tune how quickly a breath loses strength outwards from the breather. It is expected, but not required, that wide arcs lose strength more quickly over distance.
Implementation notes:
If the source grid is not the same as the target, we project along the path between them. Bolts stop if they hit anything, beams stop if they hit a wall, and balls and arcs may exhibit either bahavior. When they reach the final grid in the path, balls and arcs explode. We do not allow beams to be combined with explosions. Balls affect all floor grids in LOS (optionally, also wall grids adjacent to a grid in LOS) within their radius. Arcs do the same, but only within their cone of projection. Because affected grids are only scanned once, and it is really helpful to have explosions that travel outwards from the source, they are sorted by distance. For each distance, an adjusted damage is calculated. In successive passes, the code then displays explosion graphics, erases these graphics, marks terrain for possible later changes, affects objects, monsters, the character, and finally changes features and teleports monsters and characters in marked grids.
Usage and graphics notes:
Only 256 grids can be affected per projection, limiting the effective radius of standard ball attacks to nine units (diameter nineteen). Arcs can have larger radii; an arc capable of going out to range 20 should not be wider than 70 degrees.
Balls must explode BEFORE hitting walls, or they would affect monsters on both sides of a wall.
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 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.
References ABS, cave, cave_monster(), ddx_ddd, ddy_ddd, distance(), EVENT_BOLT, EVENT_EXPLOSION, event_signal_blast(), event_signal_bolt(), FALSE, get_angle_to_grid, handle_stuff(), health_track(), i, square::info, loc(), los(), angband_constants::max_range, monster::mflag, mflag_has, square::mon, monster_race_track(), ox, oy, panel_contains(), player_has_los_bold(), PROJECT_ARC, PROJECT_BEAM, project_f(), PROJECT_GRID, PROJECT_HIDE, PROJECT_ITEM, PROJECT_JUMP, PROJECT_KILL, project_m(), project_m_n, project_m_x, project_m_y, project_o(), project_p(), project_path(), PROJECT_PLAY, PROJECT_THRU, player::px, player::py, monster::race, sqinfo_off, sqinfo_on, square_in_bounds(), square_ispassable(), square_isproject(), square_isprojectable(), square_monster(), chunk::squares, player::timed, TRUE, player_upkeep::update, update_stuff(), player::upkeep, loc::x, loc::y, and z_info.
Referenced by effect_handler_BALL(), effect_handler_BIZARRE(), effect_handler_BREATH(), effect_handler_DARKEN_AREA(), effect_handler_LIGHT_AREA(), effect_handler_PROJECT_LOS(), effect_handler_STAR(), effect_handler_STAR_BALL(), effect_handler_SWARM(), project_aimed(), and project_touch().
Called from project() to affect terrain features.
Called for projections with the PROJECT_GRID flag set, which includes beam, ball and breath effects.
who | is the monster list index of the caster |
r | is the distance from the centre of the effect |
y | |
x | the coordinates of the grid being handled |
dam | is the "damage" from the effect at distance r from the centre |
typ | is the projection (GF_) type |
Note that this function determines if the player can see anything that happens by taking into account: blindness, line-of-sight, and illumination.
Hack – effects on grids which are memorized but not in view are also seen.
References FALSE, feature_handlers, and project_feature_handler_context_s::obvious.
Referenced by project().
Called from project() to affect monsters.
Called for projections with the PROJECT_KILL flag set, which includes bolt, beam, ball and breath effects.
who | is the monster list index of the caster |
r | is the distance from the centre of the effect |
y | |
x | the coordinates of the grid being handled |
dam | is the "damage" from the effect at distance r from the centre |
typ | is the projection (GF_) type |
flg | consists of any relevant PROJECT_ flags |
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 actual damage should be already adjusted for distance from the "epicenter" when passed in, but other effects may be influenced by r.
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 an element (e.g. 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. This should actually be coded into monster records rather than aasumed - NRM
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.
Note that this function determines if the player can see anything that happens by taking into account: blindness, line-of-sight, and illumination.
Hack – effects on grids which are memorized but not in view are also seen.
References cave, cave_monster(), project_monster_handler_context_s::dam, project_monster_handler_context_s::die_msg, FALSE, monster::fx, monster::fy, get_lore(), gf_force_obvious(), monster::hp, project_monster_handler_context_s::hurt_msg, project_monster_handler_context_s::l_ptr, project_monster_handler_context_s::m_ptr, MDESC_DEFAULT, MDESC_POSS, MDESC_PRO_VIS, monster::mflag, mflag_has, square::mon, monster_desc(), monster_handlers, monster_is_unusual(), player_upkeep::monster_race, project_monster_handler_context_s::obvious, PR_MONSTER, PROJECT_AWARE, project_m_apply_side_effects(), project_m_monster_attack(), project_m_n, project_m_player_attack(), project_m_x, project_m_y, PROJECT_SAFE, monster::race, player_upkeep::redraw, project_monster_handler_context_s::seen, project_monster_handler_context_s::skipped, square_isprojectable(), square_light_spot(), chunk::squares, TRUE, update_mon(), and player::upkeep.
Referenced by project().
Called from project() to affect objects.
Called for projections with the PROJECT_ITEM flag set, which includes beam, ball and breath effects.
who | is the monster list index of the caster |
r | is the distance from the centre of the effect |
y | |
x | the coordinates of the grid being handled |
dam | is the "damage" from the effect at distance r from the centre |
typ | is the projection (GF_) type |
Note that this function determines if the player can see anything that happens by taking into account: blindness, line-of-sight, and illumination.
Hack – effects on objects which are memorized but not in view are also seen.
References object::artifact, become_aware(), cave, cave_monster(), project_object_handler_context_s::do_kill, FALSE, project_object_handler_context_s::ignore, object::ignore, ignore_item_ok(), object::marked, object::mimicking_m_idx, msg, msgt(), object::next, project_object_handler_context_s::note_kill, object::number, object_delete(), object_desc(), object_handlers, project_object_handler_context_s::obvious, ODESC_BASE, square_excise_object(), square_light_spot(), square_object(), TRUE, and VERB_AGREEMENT.
Referenced by project().
Called from project() to affect the player.
Called for projections with the PROJECT_PLAY flag set, which includes bolt, beam, ball and breath effects.
who | is the monster list index of the caster |
r | is the distance from the centre of the effect |
y | |
x | the coordinates of the grid being handled |
dam | is the "damage" from the effect at distance r from the centre |
typ | is the projection (GF_) type |
If "r" is non-zero, then the blast was centered elsewhere; the damage is reduced in project() before being passed in here. This can happen if a monster breathes at the player and hits a wall instead.
We assume the player is aware of some effect, and always return "TRUE".
References adjust_dam(), cave, cave_monster(), disturb(), player_state::el_info, FALSE, gf_desc(), MDESC_DIED_FROM, monster::mflag, mflag_has, square::mon, monster_desc(), msg, project_player_handler_context_s::obvious, player_handlers, RANDOMISE, element_info::res_level, chunk::squares, player::state, take_hit(), player::timed, and TRUE.
Referenced by project().
Determine the path taken by a projection.
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()".
References cave, loc(), square::mon, PROJECT_STOP, PROJECT_THRU, square_isprojectable(), and chunk::squares.
Referenced by project(), projectable(), ranged_helper(), and target_set_interactive().
Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive at the final destination, assuming that no monster gets in the way, using the project_path() function to check the projection path.
Note that no grid is ever projectable() from itself.
This function is used to determine if the player can (easily) target a given grid, and if a monster can target the player.
References FALSE, angband_constants::max_range, project_path(), square_ispassable(), TRUE, loc::x, loc::y, and z_info.
Referenced by find_hiding(), make_attack_spell(), monster_list_collect(), near_permwall(), and target_able().
int project_m_n |
int project_m_x |
int project_m_y |