Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turrets fire at vehicles #39

Closed
wants to merge 13 commits into from
2 changes: 2 additions & 0 deletions data/json/monsters/defense_bot.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
"ranges": [ [ 0, 30, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 200,
"targeting_timeout_extend": -10,
Expand Down Expand Up @@ -175,6 +176,7 @@
"ranges": [ [ 0, 20, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 200,
"targeting_timeout_extend": -10,
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/drones.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@
"ranges": [ [ 0, 50, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": true,
"targeting_cost": 700,
"targeting_timeout_extend": -10,
Expand Down
3 changes: 3 additions & 0 deletions data/json/monsters/feral_humans.json
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
"fake_per": 10,
"ranges": [ [ 2, 35, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The mad militiaman fires their rifle!"
}
],
Expand Down Expand Up @@ -776,6 +777,7 @@
"//": "(ferals don't care about max-effective range.)",
"ranges": [ [ 2, 25, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The feral biker fires their shotgun!"
}
],
Expand Down Expand Up @@ -999,6 +1001,7 @@
"fake_per": 10,
"ranges": [ [ 2, 14, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The feral officer fires their M18!"
}
],
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/mi-go.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"fake_dex": 8,
"fake_per": 8,
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The mi-go scout fires its weapon!",
"ranges": [ [ 2, 30, "DEFAULT" ] ]
}
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/robofac_robots.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"cooldown": 1,
"gun_type": "v29_turret",
"fake_skills": [ [ "gun", 4 ], [ "pistol", 4 ] ],
"target_moving_vehicles": true,
"ranges": [ [ 0, 30, "DEFAULT" ] ]
}
],
Expand Down
3 changes: 3 additions & 0 deletions data/json/monsters/turrets.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
"ranges": [ [ 0, 40, "AUTO" ], [ 41, 110, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 200,
"targeting_timeout_extend": -10,
Expand Down Expand Up @@ -175,6 +176,7 @@
"ranges": [ [ 0, 36, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 200,
"targeting_timeout_extend": -10,
Expand Down Expand Up @@ -235,6 +237,7 @@
"ranges": [ [ 0, 60, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 200,
"targeting_timeout_extend": -10,
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/yrax.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"ranges": [ [ 0, 25, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": true,
"targeting_sound": "a fast sequence of clicking tones.",
"targeting_volume": 50,
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/zed-animal.json
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@
"fake_dex": 4,
"fake_per": 4,
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The vicious vicuña spits a glob of acid!",
"ranges": [ [ 2, 10, "DEFAULT" ] ]
},
Expand Down
1 change: 1 addition & 0 deletions data/json/monsters/zed_acid.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"fake_dex": 8,
"fake_per": 8,
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The corrosive zombie spits a glob of acid!",
"ranges": [ [ 2, 10, "DEFAULT" ] ]
},
Expand Down
2 changes: 2 additions & 0 deletions data/json/monsters/zed_soldiers.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@
"fake_dex": 8,
"fake_per": 8,
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The %s launches a corrosive dart!",
"ranges": [ [ 2, 20, "DEFAULT" ] ]
}
Expand Down Expand Up @@ -180,6 +181,7 @@
"fake_dex": 8,
"fake_per": 8,
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The %s launches a hail of corrosive darts!",
"ranges": [ [ 2, 8, "DEFAULT" ] ]
}
Expand Down
1 change: 1 addition & 0 deletions data/mods/DinoMod/monsters/dinosaur_CBM.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"ranges": [ [ 0, 30, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 1,
"targeting_timeout_extend": -1,
Expand Down
1 change: 1 addition & 0 deletions data/mods/DinoMod/monsters/zed-dinosaur_CBM.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"ranges": [ [ 0, 30, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 1,
"targeting_timeout_extend": -1,
Expand Down
3 changes: 3 additions & 0 deletions data/mods/Xedra_Evolved/monsters/bloodsuckers.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
"fake_per": 10,
"ranges": [ [ 2, 14, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The renfield fires their Glock!"
}
],
Expand Down Expand Up @@ -253,6 +254,7 @@
"//": "(ferals don't care about max-effective range.)",
"ranges": [ [ 2, 25, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The renfield fires their shotgun!"
}
],
Expand Down Expand Up @@ -318,6 +320,7 @@
"no_ammo_sound": "hiss!",
"ranges": [ [ 0, 10, "DEFAULT" ] ],
"require_targeting_player": false,
"target_moving_vehicles": true,
"description": "The renfield shoots their flamethrower!"
}
],
Expand Down
1 change: 1 addition & 0 deletions data/mods/Xedra_Evolved/monsters/exodii.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"ranges": [ [ 4, 41, "DEFAULT" ] ],
"require_targeting_npc": true,
"require_targeting_monster": true,
"target_moving_vehicles": true,
"laser_lock": false,
"targeting_cost": 400,
"targeting_timeout_extend": -10,
Expand Down
1 change: 1 addition & 0 deletions doc/MONSTER_SPECIAL_ATTACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ The monster fires a gun at a target. If the monster is friendly, it will avoid
| `require_targeting_player` | If true, the monster will need to "target" the player, wasting `targeting_cost` moves, putting the attack on cooldown and making warning sounds, unless it attacked something that needs to be targeted recently. Gives "grace period" to player. |
| `require_targeting_npc` | As above, but with NPCs. |
| `require_targeting_monster` | As above, but with monsters. |
| 'target_moving_vehicles' | If true, the monster will "target" moving vehicles even if it cannot see the player.
| `targeting_timeout` | Targeting status will be applied for this many turns. Note that targeting applies to turret, not targets. |
| `targeting_timeout_extend` | Successfully attacking will extend the targeting for this many turns. Can be negative. |
| `targeting_cost` | Move cost of targeting the player. Only applied if attacking the player and didn't target player within last 5 turns. |
Expand Down
35 changes: 35 additions & 0 deletions src/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,41 @@ bool map::deregister_vehicle_zone( zone_data &zone ) const
return false;
}

std::set<tripoint_bub_ms> map::get_moving_vehicle_targets( const Creature &z, int max_range )
{
const tripoint_bub_ms zpos( z.pos() );
std::set<tripoint_bub_ms> priority;
std::set<tripoint_bub_ms> visible;
for( wrapped_vehicle &v : get_vehicles() ) {
if( !v.v->is_moving() ) {
continue;
}
if( !fov_3d && v.pos.z != zpos.z() ) {
continue;
}
if( rl_dist( zpos, tripoint_bub_ms( v.pos ) ) > max_range + 40 ) {
continue; // coarse distance filter, 40 = ~24 * sqrt(2) - rough max diameter of a vehicle
}
for( const vpart_reference &vpr : v.v->get_all_parts() ) {
const tripoint_bub_ms vppos = static_cast<tripoint_bub_ms>( vpr.pos() );
if( rl_dist( zpos, vppos ) > max_range ) {
continue;
}
if( !z.sees( vppos ) ) {
continue;
}
if( vpr.has_feature( VPFLAG_CONTROLS ) ||
vpr.has_feature( VPFLAG_ENGINE ) ||
vpr.has_feature( VPFLAG_WHEEL ) ) {
priority.emplace( vppos );
} else {
visible.emplace( vppos );
}
}
}
return !priority.empty() ? priority : visible;
}

// 3D vehicle functions

VehicleList map::get_vehicles( const tripoint &start, const tripoint &end )
Expand Down
4 changes: 4 additions & 0 deletions src/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,10 @@ class map
std::vector<zone_data *> get_vehicle_zones( int zlev );
void register_vehicle_zone( vehicle *, int zlev );
bool deregister_vehicle_zone( zone_data &zone ) const;
// returns a list of tripoints which contain parts from moving vehicles within \p max_range
// distance from \p source position, if any parts are CONTROLS, ENGINE or WHEELS returns a
// list of tripoints with exclusively such parts instead. Used for monster gun actor targeting.
std::set<tripoint_bub_ms> get_moving_vehicle_targets( const Creature &source, int max_range );

// Removes vehicle from map and returns it in unique_ptr
std::unique_ptr<vehicle> detach_vehicle( vehicle *veh );
Expand Down
32 changes: 26 additions & 6 deletions src/mattack_actors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "translations.h"
#include "viewer.h"


static const efftype_id effect_badpoison( "badpoison" );
static const efftype_id effect_bite( "bite" );
static const efftype_id effect_grabbed( "grabbed" );
Expand Down Expand Up @@ -809,6 +810,8 @@ void gun_actor::load_internal( const JsonObject &obj, const std::string & )

laser_lock = obj.get_bool( "laser_lock", false );

obj.read( "target_moving_vehicles", target_moving_vehicles );

obj.read( "require_sunlight", require_sunlight );
}

Expand All @@ -831,6 +834,8 @@ int gun_actor::get_max_range() const
bool gun_actor::call( monster &z ) const
{
Creature *target;
tripoint aim_at;
bool untargeted = false;

if( z.friendly ) {
int max_range = get_max_range();
Expand All @@ -847,20 +852,35 @@ bool gun_actor::call( monster &z ) const
}
return false;
}

aim_at = target->pos();
} else {
target = z.attack_target();
aim_at = target ? target->pos() : tripoint_zero;
if( !target || !z.sees( *target ) || ( !target->is_monster() && !z.aggro_character ) ) {
return false;
if( !target_moving_vehicles ) {
return false;
}
untargeted = true; // no living targets, try to find moving car parts
const std::set<tripoint_bub_ms> moving_veh_parts = get_map()
.get_moving_vehicle_targets( z, get_max_range() );
if( moving_veh_parts.empty() ) {
return false;
}
aim_at = random_entry( moving_veh_parts, tripoint_bub_ms() ).raw();
}
}

int dist = rl_dist( z.pos(), target->pos() );
add_msg_debug( debugmode::DF_MATTACK, "Target %s at range %d", target->disp_name(), dist );
const int dist = rl_dist( z.pos(), aim_at );
if( target ) {
add_msg_debug( debugmode::DF_MATTACK, "Target %s at range %d", target->disp_name(), dist );
} else {
add_msg_debug( debugmode::DF_MATTACK, "Shooting at vehicle at range %d", dist );
}

for( const auto &e : ranges ) {
if( dist >= e.first.first && dist <= e.first.second ) {
if( try_target( z, *target ) ) {
shoot( z, target->pos(), e.second );
if( untargeted || try_target( z, *target ) ) {
shoot( z, aim_at, e.second );
}
return true;
}
Expand Down
2 changes: 2 additions & 0 deletions src/mattack_actors.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ class gun_actor : public mattack_actor
/** Number of moves required for each attack */
int move_cost = 150;

/** Should moving vehicles be targeted */
bool target_moving_vehicles = false;
/*@{*/
/** Turrets may need to expend moves targeting before firing on certain targets */

Expand Down