1 #pragma once 2 3 #include <vector> 4 5 #include "beam.h" 6 #include "los-type.h" 7 #include "reach-type.h" 8 9 using std::vector; 10 11 struct passwall_path; 12 13 enum aff_type // sign and non-zeroness matters 14 { 15 AFF_TRACER = -1, 16 AFF_NO = 0, 17 AFF_MAYBE = 1, // can possibly affect 18 AFF_YES, // intended/likely to affect 19 // If you want to extend this to pass the probability somehow, feel free to, 20 // just keep AFF_YES the minimal "bright" value. 21 AFF_LANDING, // Valid shadow step landing site 22 AFF_MULTIPLE, // Passes through multiple times 23 }; 24 25 class targeter 26 { 27 public: targeter()28 targeter() : agent(nullptr), obeys_mesmerise(false) {}; ~targeter()29 virtual ~targeter() {}; 30 31 coord_def origin; 32 coord_def aim; 33 const actor* agent; 34 string why_not; 35 bool obeys_mesmerise; // whether the rendering of ranges should take into account mesmerise effects 36 37 virtual bool set_aim(coord_def a); 38 virtual bool valid_aim(coord_def a) = 0; 39 virtual bool can_affect_outside_range(); 40 virtual bool can_affect_walls(); 41 42 virtual aff_type is_affected(coord_def loc) = 0; 43 virtual bool can_affect_unseen(); 44 virtual bool affects_monster(const monster_info& mon); 45 protected: 46 bool anyone_there(coord_def loc); 47 }; 48 49 class targeter_beam : public targeter 50 { 51 public: 52 targeter_beam(const actor *act, int range, zap_type zap, int pow, 53 int min_expl_rad, int max_expl_rad); 54 bolt beam; 55 virtual bool set_aim(coord_def a) override; 56 bool valid_aim(coord_def a) override; 57 bool can_affect_outside_range() override; 58 virtual aff_type is_affected(coord_def loc) override; 59 virtual bool affects_monster(const monster_info& mon) override; 60 protected: 61 vector<coord_def> path_taken; // Path beam took. 62 void set_explosion_aim(bolt tempbeam); 63 void set_explosion_target(bolt &tempbeam); 64 int min_expl_rad, max_expl_rad; 65 int range; 66 private: 67 bool penetrates_targets; 68 explosion_map exp_map_min, exp_map_max; 69 }; 70 71 class targeter_unravelling : public targeter_beam 72 { 73 public: 74 targeter_unravelling(const actor *act, int range, int pow); 75 bool set_aim(coord_def a) override; 76 }; 77 78 class targeter_view : public targeter 79 { 80 public: 81 targeter_view(); 82 bool valid_aim(coord_def a) override; 83 aff_type is_affected(coord_def loc) override; 84 }; 85 86 class targeter_smite : public targeter 87 { 88 public: 89 targeter_smite(const actor *act, int range = LOS_RADIUS, 90 int exp_min = 0, int exp_max = 0, bool wall_ok = false, 91 bool (*affects_pos_func)(const coord_def &) = 0); 92 virtual bool set_aim(coord_def a) override; 93 virtual bool valid_aim(coord_def a) override; 94 virtual bool can_affect_outside_range() override; 95 bool can_affect_walls() override; 96 aff_type is_affected(coord_def loc) override; 97 protected: 98 // assumes exp_map is valid only if >0, so let's keep it private 99 int exp_range_min, exp_range_max; 100 explosion_map exp_map_min, exp_map_max; 101 int range; 102 private: 103 bool affects_walls; 104 bool (*affects_pos)(const coord_def &); 105 }; 106 107 class targeter_walljump : public targeter_smite 108 { 109 public: 110 targeter_walljump(); 111 aff_type is_affected(coord_def loc) override; 112 bool valid_aim(coord_def a) override; 113 }; 114 115 class targeter_transference : public targeter_smite 116 { 117 public: 118 targeter_transference(const actor *act, int aoe); 119 bool valid_aim(coord_def a) override; 120 }; 121 122 class targeter_fragment : public targeter_smite 123 { 124 public: 125 targeter_fragment(const actor *act, int power, int range = LOS_RADIUS); 126 bool set_aim(coord_def a) override; 127 bool valid_aim(coord_def a) override; 128 private: 129 int pow; 130 }; 131 132 class targeter_reach : public targeter 133 { 134 public: 135 targeter_reach(const actor* act, reach_type ran = REACH_NONE); 136 reach_type range; 137 bool valid_aim(coord_def a) override; 138 aff_type is_affected(coord_def loc) override; 139 }; 140 141 class targeter_cleave : public targeter 142 { 143 public: 144 targeter_cleave(const actor* act, coord_def target); 145 aff_type is_affected(coord_def loc) override; 146 bool valid_aim(coord_def) override; 147 bool set_aim(coord_def a) override; 148 private: 149 set<coord_def> targets; 150 }; 151 152 class targeter_cloud : public targeter 153 { 154 public: 155 targeter_cloud(const actor* act, int range = LOS_RADIUS, 156 int count_min = 8, int count_max = 10); 157 bool set_aim(coord_def a) override; 158 bool valid_aim(coord_def a) override; 159 bool can_affect_outside_range() override; 160 aff_type is_affected(coord_def loc) override; 161 int range; 162 int cnt_min, cnt_max; 163 map<coord_def, aff_type> seen; 164 vector<vector<coord_def> > queue; 165 bool avoid_clouds; 166 }; 167 168 // TODO: this should be based on targeter_beam instead 169 class targeter_splash : public targeter 170 { 171 public: 172 targeter_splash(const actor *act, int ran); 173 bool valid_aim(coord_def a) override; 174 aff_type is_affected(coord_def loc) override; 175 private: 176 int range; 177 }; 178 179 class targeter_radius : public targeter 180 { 181 public: 182 targeter_radius(const actor *act, los_type _los = LOS_DEFAULT, 183 int ran = LOS_RADIUS, int ran_max = 0, int ran_min = 0); 184 bool valid_aim(coord_def a) override; 185 virtual aff_type is_affected(coord_def loc) override; 186 private: 187 los_type los; 188 int range, range_max, range_min; 189 }; 190 191 // like targeter_radius, but converts all AFF_YESes to AFF_MAYBE 192 class targeter_maybe_radius : public targeter_radius 193 { 194 public: 195 targeter_maybe_radius(const actor *act, los_type _los = LOS_DEFAULT, 196 int ran = LOS_RADIUS, int ran_max = 0, int ran_min = 0) targeter_radius(act,_los,ran,ran_max,ran_min)197 : targeter_radius(act, _los, ran, ran_max, ran_min) 198 { } 199 is_affected(coord_def loc)200 virtual aff_type is_affected(coord_def loc) override 201 { 202 if (targeter_radius::is_affected(loc)) 203 return AFF_MAYBE; 204 else 205 return AFF_NO; 206 } 207 }; 208 209 class targeter_thunderbolt : public targeter 210 { 211 public: 212 targeter_thunderbolt(const actor *act, int r, coord_def _prev); 213 214 bool valid_aim(coord_def a) override; 215 bool set_aim(coord_def a) override; 216 aff_type is_affected(coord_def loc) override; 217 map<coord_def, aff_type> zapped; 218 FixedVector<int, LOS_RADIUS + 1> arc_length; 219 private: 220 coord_def prev; 221 int range; 222 }; 223 224 enum class shadow_step_blocked 225 { 226 none, 227 occupied, 228 move, 229 path, 230 no_target, 231 }; 232 233 class targeter_shadow_step : public targeter 234 { 235 public: 236 targeter_shadow_step(const actor* act, int r); 237 238 bool valid_aim(coord_def a) override; 239 bool set_aim(coord_def a) override; 240 bool step_is_blocked; 241 aff_type is_affected(coord_def loc) override; 242 bool has_additional_sites(coord_def a); 243 set<coord_def> additional_sites; 244 coord_def landing_site; 245 private: 246 void set_additional_sites(coord_def a); 247 void get_additional_sites(coord_def a); 248 bool valid_landing(coord_def a, bool check_invis = true); 249 shadow_step_blocked no_landing_reason; 250 shadow_step_blocked blocked_landing_reason; 251 set<coord_def> temp_sites; 252 int range; 253 }; 254 255 class targeter_cone : public targeter 256 { 257 public: 258 targeter_cone(const actor *act, int r); 259 260 bool valid_aim(coord_def a) override; 261 bool set_aim(coord_def a) override; 262 aff_type is_affected(coord_def loc) override; 263 map<coord_def, aff_type> zapped; 264 FixedVector< map<coord_def, aff_type>, LOS_RADIUS + 1 > sweep; 265 private: 266 int range; 267 }; 268 269 #define CLOUD_CONE_BEAM_COUNT 11 270 271 class targeter_shotgun : public targeter 272 { 273 public: 274 targeter_shotgun(const actor* act, size_t beam_count, int r, 275 bool cloud = false); 276 bool valid_aim(coord_def a) override; 277 bool set_aim(coord_def a) override; 278 aff_type is_affected(coord_def loc) override; 279 vector<ray_def> rays; 280 map<coord_def, size_t> zapped; 281 private: 282 size_t num_beams; 283 int range; 284 bool uses_clouds; 285 }; 286 287 class targeter_monster_sequence : public targeter_beam 288 { 289 public: 290 targeter_monster_sequence(const actor *act, int pow, int range); 291 bool set_aim(coord_def a); 292 bool valid_aim(coord_def a); 293 aff_type is_affected(coord_def loc); 294 private: 295 explosion_map exp_map; 296 }; 297 298 class targeter_passwall : public targeter_smite 299 { 300 public: 301 targeter_passwall(int max_range); 302 bool set_aim(coord_def a) override; 303 bool valid_aim(coord_def a) override; 304 aff_type is_affected(coord_def loc) override; 305 bool can_affect_outside_range() override; 306 bool can_affect_unseen() override; 307 bool affects_monster(const monster_info& mon) override; 308 309 private: 310 unique_ptr<passwall_path> cur_path; 311 }; 312 313 class targeter_dig : public targeter_beam 314 { 315 public: 316 targeter_dig(int max_range); 317 bool valid_aim(coord_def a) override; 318 aff_type is_affected(coord_def loc) override; 319 bool can_affect_unseen() override; 320 bool can_affect_walls() override; 321 bool affects_monster(const monster_info& mon) override; 322 private: 323 map<coord_def, int> aim_test_cache; 324 }; 325 326 class targeter_overgrow: public targeter 327 { 328 public: 329 targeter_overgrow(); can_affect_walls()330 bool can_affect_walls() override { return true; } 331 bool valid_aim(coord_def a) override; 332 aff_type is_affected(coord_def loc) override; 333 bool set_aim(coord_def a) override; 334 set<coord_def> affected_positions; 335 private: 336 bool overgrow_affects_pos(const coord_def &p); 337 }; 338 339 class targeter_charge : public targeter 340 { 341 public: 342 targeter_charge(const actor *act, int range); 343 bool valid_aim(coord_def a) override; 344 bool set_aim(coord_def a) override; 345 aff_type is_affected(coord_def loc) override; 346 private: 347 int range; 348 vector<coord_def> path_taken; // Path the charge took. 349 }; 350 351 string bad_charge_target(coord_def a); 352 bool can_charge_through_mons(coord_def a); 353 354 // a fixed los targeter matching how it is called for shatter, with a custom 355 // tweak to affect walls. 356 class targeter_shatter : public targeter_radius 357 { 358 public: targeter_shatter(const actor * act)359 targeter_shatter(const actor *act) : targeter_radius(act, LOS_ARENA) { } can_affect_walls()360 bool can_affect_walls() override { return true; } 361 aff_type is_affected(coord_def loc) override; 362 }; 363 364 // A fixed targeter for multi-position attacks, i.e. los stuff that 365 // affects various squares, or monsters non-locally. For los stuff that 366 // affects only monsters on a per-monster case basis see targeter_multimonster 367 class targeter_multiposition : public targeter 368 { 369 public: 370 targeter_multiposition(const actor *a, vector<coord_def> seeds, 371 aff_type _positive=AFF_MAYBE); 372 targeter_multiposition(const actor *a, vector<monster *> seeds, 373 aff_type _positive=AFF_MAYBE); 374 targeter_multiposition(const actor *a, initializer_list<coord_def> seeds, 375 aff_type _positive=AFF_MAYBE); 376 377 void add_position(const coord_def &c, bool force=false); valid_aim(coord_def)378 bool valid_aim(coord_def) override { return true; } 379 aff_type is_affected(coord_def loc) override; 380 381 protected: 382 set<coord_def> affected_positions; 383 aff_type positive; 384 }; 385 386 class targeter_chain_lightning : public targeter 387 { 388 public: 389 targeter_chain_lightning(); valid_aim(coord_def)390 bool valid_aim(coord_def) override { return true; } 391 aff_type is_affected(coord_def loc) override; 392 private: 393 set<coord_def> potential_victims; 394 set<coord_def> closest_victims; 395 }; 396 397 // A static targeter for Maxwell's Coupling 398 // that finds the closest monster using the absolute zero code. 399 class targeter_maxwells_coupling : public targeter_multiposition 400 { 401 public: 402 targeter_maxwells_coupling(); 403 }; 404 405 class targeter_multifireball : public targeter_multiposition 406 { 407 public: 408 targeter_multifireball(const actor *a, vector<coord_def> seeds); 409 }; 410 411 // this is implemented a bit like multifireball, but with some tweaks 412 class targeter_ramparts : public targeter_multiposition 413 { 414 public: 415 targeter_ramparts(const actor *a); 416 417 aff_type is_affected(coord_def loc) override; can_affect_walls()418 bool can_affect_walls() override { return true; } 419 }; 420 421 // a class for fixed beams at some offset from the player 422 class targeter_starburst_beam : public targeter_beam 423 { 424 public: 425 targeter_starburst_beam(const actor *a, int _range, int pow, const coord_def &offset); 426 // this is a bit of ui hack: lets us set starburst beams even when the 427 // endpoint would be out of los can_affect_unseen()428 bool can_affect_unseen() override { return true; } valid_aim(coord_def)429 bool valid_aim(coord_def) override { return true; } 430 }; 431 432 class targeter_starburst : public targeter 433 { 434 public: 435 targeter_starburst(const actor *a, int range, int pow); valid_aim(coord_def)436 bool valid_aim(coord_def) override { return true; } 437 aff_type is_affected(coord_def loc) override; 438 vector<targeter_starburst_beam> beams; 439 }; 440 441 // A targeter for Eringya's Noxious Bog that finds cells that can be bogged. 442 class targeter_bog : public targeter_multiposition 443 { 444 public: 445 targeter_bog(const actor *a, int pow); 446 }; 447 448 class targeter_ignite_poison : public targeter_multiposition 449 { 450 public: 451 targeter_ignite_poison(actor *a); 452 }; 453 454 class targeter_multimonster : public targeter 455 { 456 public: 457 targeter_multimonster(const actor *a); 458 valid_aim(coord_def)459 bool valid_aim(coord_def) override { return true; } 460 aff_type is_affected(coord_def loc) override; 461 protected: 462 bool check_monster; 463 }; 464 465 class targeter_drain_life : public targeter_multimonster 466 { 467 public: 468 targeter_drain_life(); 469 bool affects_monster(const monster_info& mon) override; 470 }; 471 472 class targeter_discord : public targeter_multimonster 473 { 474 public: 475 targeter_discord(); 476 bool affects_monster(const monster_info& mon) override; 477 }; 478 479 class targeter_englaciate : public targeter_multimonster 480 { 481 public: 482 targeter_englaciate(); 483 bool affects_monster(const monster_info& mon) override; 484 }; 485 486 class targeter_fear : public targeter_multimonster 487 { 488 public: 489 targeter_fear(); 490 bool affects_monster(const monster_info& mon) override; 491 }; 492 493 class targeter_intoxicate : public targeter_multimonster 494 { 495 public: 496 targeter_intoxicate(); 497 bool affects_monster(const monster_info& mon) override; 498 }; 499