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

Automatic aim ai rework #10601

Merged
merged 11 commits into from Dec 26, 2014

Conversation

Projects
None yet
5 participants
@Coolthulhu
Copy link
Contributor

commented Dec 22, 2014

Changes quite significantly the behavior of some hacked bots (tested on tanks, chickens and skitterbots) and turrets with area of effect attacks.

Hacked bots will no longer depend on distance from player to pick an attack and will not skip turns if they can't see the player. Before, they'd attack zombies with the same attack they'd use to attack the player.

Bots (skitters, tanks and chickens) can now zap enemies when hacked. Currently this is always successful when attempted (because player can only dodge tazing with uncanny_dodge). Stun times and damage copied from iuse::tazer.

Made mutant-ignoring turrets attack mutants driving vehicles, because weird animals don't drive vehicles.

Moved range setting of turrets from hardcoded to a json member.

Made turrets consider area of effect of their projectiles. They will ignore any target too close to attack without risking including self in the area of effect.

During my testing it worked nicely, so it's probably fully or at least mostly functional.
I changed the structure of monattack.cpp quite significantly. I moved aiming from functions like frag_tur up to the functions that use them, like multi_robot and chickenbot (otherwise hacked chickens and tanks would aim twice per attack).

I sent a conflicting PR yesterday (manual turrets - conflicting on incredibly minor things, but still), so this is more for a review right now.

Coolthulhu added some commits Dec 22, 2014

Rework turret and monster turret AI
Makes hacked bots much less dependent on player
@Rivet-the-Zombie

This comment has been minimized.

Copy link
Member

commented Dec 22, 2014

Nice!

const std::string ammo_type("120mm_HEAT");
// Make sure our ammo isn't weird.
if (z->ammo[ammo_type] > 40) {
debugmsg("Generated too much ammo (%d) for %s in mattack::tank_tur", z->ammo[ammo_type], z->name().c_str());
debugmsg("Generated too much ammo (%d) for %s in mattack::tank_gun", z->ammo[ammo_type], z->name().c_str());

This comment has been minimized.

Copy link
@KA101

KA101 Dec 22, 2014

Contributor

You removed the underscore elsewhere, may as well nail it here too.

@KA101 KA101 assigned KA101 and unassigned KA101 Dec 22, 2014

if( z->friendly != 0 ) {
// Let friendly bots taze too
for( size_t i = 0; i < g->num_zombies(); i++ ) {
monster *tmp = &( g->zombie( i ) );

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 22, 2014

Contributor

Why a pointer and not a reference? Also, below, the this-> is redundant.

g->u.worn_with_flag("ELECTRIC_IMMUNE")) { //Resistances applied.
add_msg(m_info, _("The %s unsuccessfully attempts to shock you."), z->name().c_str());
return;
if( target == &g->u ) {

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 22, 2014

Contributor

Player character and npcs can use the same branch, a npc is "kind of a player", npcs have the very same functions that a player has. Also, below the add_msg will be shown when the npcs or the monster is not visible to the player. add_msg_player_or_npc will handle that case.

And why is the npc hurt differently than the player? hurtall(rng(5,20)) vs apply_damag(rng(1,3)*rng(1,5))

This comment has been minimized.

Copy link
@KA101

KA101 Dec 25, 2014

Contributor

Not sure why these weren't fixed but I'll implement in the merge.

@@ -13440,27 +13436,43 @@ Creature *player::auto_find_hostile_target(int range, int &boo_hoo, int &fire_t)
targets.push_back( p );
}
for( auto &m : targets ) {
if (!sees(m, t)) {
// inline player::sees because we're static now

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 23, 2014

Contributor

This code "nicely" ignores the (non) visibility of digging or submerged monsters. That thing was handled in player::sees.
Edit: and it considers hallucinations, but I assume that most code in monattack does this.

This comment has been minimized.

Copy link
@kevingranade

kevingranade Dec 23, 2014

Member

If by "inline" you mean "copy the contents of player::sees(), please don't, it's just asking for it to go out of sync at some point in the future.
It's much preferable to extract it to some third location and have it included in both player and monster. Possibly reasonable to go in creature, but then again what would be really nice is a new class that has an instance included in both.
For now just avoid duplicating the code by extracting it somewhere as a helper function or something.

@@ -13401,27 +13401,23 @@ Creature::Attitude player::attitude_to( const Creature &other ) const
return A_NEUTRAL;
}

Creature *player::auto_find_hostile_target(int range, int &boo_hoo, int &fire_t)
Creature *player::auto_find_hostile_target(point pos, int range, int &boo_hoo, int area)

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 23, 2014

Contributor

fire_t is very important, why have you removed it?

z->moves -= 500; // It takes a while
std::vector<point> traj = line_to(z->posx(), z->posy(), target->xpos(), target->ypos(), fire_t);
std::vector<point> traj = line_to(z->posx(), z->posy(), target->xpos(), target->ypos(), 0);

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 23, 2014

Contributor

line_to will generate different lines depending on that t parameter, map::sees uses the same code. It's quite likely that one of those lines allows seeing the target , while another line goes through opaque terrain and does not allow the point to be seen. The sees function stores the number that will create a line through transparent terrain in the t parameter. Passing the same value to line_to ensure that the generate line is the same as the line used by sees.

@Coolthulhu

This comment has been minimized.

Copy link
Contributor Author

commented Dec 23, 2014

OK, I get most of those, except the fire_t one.

I removed fire_t, because the only function that used it was flamethrower. All others would simply declare it, then forget about it as soon as auto_find_hostile_target returned. What is it used for? Does it ensure the fire trail follows the correct path or something?

EDIT: Tazing has different damage for player and NPC, because player taze code is from monster function, while NPC one is from iuse::tazer. Should I nerf NPC taze back to player taze level?

// code copied form mattack::smg, mattack::flamethrower
int range = ammo.type == fuel_type_gasoline ? 5 : 12;
int range = part_info( p ).range;
if( range < 1 ) {

This comment has been minimized.

Copy link
@BevapDin

BevapDin Dec 23, 2014

Contributor

Instead of setting this here, why not as the default value when it's loaded from json: jo.get_int("range", 12)

@BevapDin

This comment has been minimized.

Copy link
Contributor

commented Dec 23, 2014

map::sees checks several lines, if any of them allows seeing the target, it returns true and stores the "number" of that line in the t parameters. Later line_to uses that parameter to generate the same line that sees had been using. If line_to would use a different t value and thereby generate a different line, it would fire through solid/opaque terrain, even when the shooter can clearly see the target and knows a clear path to it.

You can try this out: go into ranged.cpp, there are several places that have

int t;
if(sees(..., t)) {
   traj = line_to(..., t);
} else {
   traj = line_to(..., 0);
}

Change them to always use 0 as t parameter and no sees check:

traj = line_to(..., 0);

Than try to aim along a wall:

@
###########Z
          #   Z
          #     Z
@Coolthulhu

This comment has been minimized.

Copy link
Contributor Author

commented Dec 23, 2014

Is it OK if I retrace the lines for the bresenham value? It (the bresenham parameter) is only used in flamethrower code and map::sees is checked for every monster loaded, so it shouldn't be expensive to check it once more for one monster 5 tiles from us.

Flamethrowers are back to being perfectly accurate.

@BevapDin

This comment has been minimized.

Copy link
Contributor

commented Dec 23, 2014

I removed fire_t, because the only function that used it was flamethrower. All others would simply declare it, then forget about it as soon as auto_find_hostile_target returned.

That is either a bug, or the functions call player::fire_gun, which does the the same process again: calling map::sees, taking the t parameter from there, so they don't need the already calculated value from fire_t.

Is it OK if I retrace the lines for the bresenham value?

Sure. I'm only aware of this bresenham line thing as I once tried to remove that parameter from all line_to and sees calls (always using the default line), and that had terrible results.

@KA101

This comment has been minimized.

Copy link
Contributor

commented Dec 25, 2014

OK, rebase this and I'll see about fast-tracking it.

Coolthulhu added some commits Dec 25, 2014

Merge branch 'master' into automatic-aim-ai
Conflicts:
	src/player.cpp
	src/vehicle.cpp
@Coolthulhu

This comment has been minimized.

Copy link
Contributor Author

commented Dec 25, 2014

Seems to work after merge. At least I couldn't get it to not-work.

@KA101 KA101 self-assigned this Dec 25, 2014

} else if( target->is_npc() ) {
npc *foe = dynamic_cast< npc* >( target );
int shock = rng(5, 20);
foe->moves -= shock * 100;

This comment has been minimized.

Copy link
@KA101

KA101 Dec 25, 2014

Contributor

Differential stun-amounts are suboptimal. Knocking 'em all to 1-20 damage and 50x move-loss multiplier. Net effect, taser's less effective at stunlocking critters/NPCs and more effective at stunlocking you. Nerf.

@KA101

This comment has been minimized.

Copy link
Contributor

commented Dec 25, 2014

Changed the message but in testing the skitterbot refused to target the nearby NPC, instead tazing me whenever I got within 2-3 tiles.

Bug: tazers don't have that much reach and the NPC was the active threat. Sorry, sending it back.

@KA101 KA101 removed their assignment Dec 25, 2014

Coolthulhu added some commits Dec 25, 2014

@Coolthulhu

This comment has been minimized.

Copy link
Contributor Author

commented Dec 25, 2014

OK, I added tazing NPCs, either hostile or non-hostile (depending on mon's attitude). I didn't include your balancing change, because it kinda goes out of scope. Also because skitterbots are quite scary to new survivors already.

I nerfed NPC tazing to player tazing level. NPCs who somehow managed to acquired immunity to electricity should now be immune to tazing (I couldn't think of a good way of testing if it works, though).
Monsters will be tazed as hard as with a player-wielded tazer. IMO this makes sense, because hacked bots with tazers are probably going to be tank drones or chicken walkers rather than skitterbots. Eventually this should probably be split into tazer and "lightning gun", but I'd rather keep balancing out of this PR.

I discovered a problem with friendly monster AI vs. hostile NPCs, but it also is out of scope of this PR. Friendly mons can stumble into tiles occupied by hostile NPCs.

@BevapDin

This comment has been minimized.

Copy link

commented on src/monattack.cpp in a0f7386 Dec 25, 2014

You can use player::add_msg_if_player_or_npc here. Is has the additional advantage that it prevents messages if the npc can not be seen by the player.

Same below, calling die on g->u is fine, you can skip the check for foe being g->u and call die directly. Note however that you can not erase g->u from the active npc list, that still needs a check for foe being a npc.

@KA101

This comment has been minimized.

Copy link
Contributor

commented Dec 25, 2014

Fair enough on the change, that was to reconcile the three different standards (which you now have) and we can revisit it later if need be. Might want to implement BevapDin's there though.

@Coolthulhu

This comment has been minimized.

Copy link
Contributor Author

commented Dec 25, 2014

That failed check is bot losing connection, not a compilation failure.

@KA101

This comment has been minimized.

Copy link
Contributor

commented Dec 25, 2014

Nice to see someone clicking the details link. ;-)

@KA101 KA101 self-assigned this Dec 25, 2014

@KA101

This comment has been minimized.

Copy link
Contributor

commented Dec 26, 2014

Next is gonna be tweaking it to not use explosive rounds on squirrels, cats, etc but for now I think it's workable.

@KA101 KA101 merged commit 56a7392 into CleverRaven:master Dec 26, 2014

1 check passed

default
Details

@Coolthulhu Coolthulhu deleted the cataclysmbnteam:automatic-aim-ai branch Dec 28, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.