default tactics #269

Parent #1Owner #361Flags read, fertileSource hellcore/hellcore.db

Aliases: default tactics, tactics

5 verbs · 23 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
decide_on_actionthis none thisrxd#26917
consider_grabthis none thisrxd#26912
consider_dodgethis none thisrxd#26910
consider_pushthis none thisrxd#26927
tree_tagthis none thisrxd#2691

Properties

PropertyDefinerFlagsOwnerValue
powerattack_base_chance#269rc#36116
powerattack_eval_multiplier#269rc#3612.0
feint_base_chance#269rc#3610
feint_eval_multiplier#269rc#3615.0
dodge_base_chance#269rc#361100
dodge_eval_multiplier#269rc#3611.0
grab_base_chance#269rc#3610
grab_eval_multiplier#269rc#3610.0
brains_requirement#269rc#3616
considerations#269rc#361{"dodge", "grab", "push"}
help_msg#269rc#361
list of 7{"A tactics object is an object for making fast, stateless attack decisions in combat. It is called by NPCs in $npc:_fight to determine whether to make a special move, such as a feint, powerattack or dodge. An NPC can define a .tactics property, which can either be a tactics object or a list of tactics objects. In the latter case, a random object will be selected from the list each time :_fight is called. If .tactics is not defined, $tactics.default will be used.", "", "To decide on an attack, a the verb :decide_on_action is called on the tactics object. This will return either an action-spec (to be as arguments to :queue_action) or 0. The tactics object isn't responsible for returning \"normal\" attacks, that's done by :_fight itself.", "", "$tactics.default and its children implements :decide_on_action in a way that allows easy customization. The property .considerations contains a list of strings determining which attacks to consider. For an entry \"specialmove\" in the list, the verb :consider_specialmove is called on the tactics object (for example, \"powerattack\" and :consider_powerattack). Additionally, the property .brains_requirement is a minimum (total) brains requirement. :decide_on_action will always return 0 for monsters that do not fulfill this requirement.", "", "For each consideration verb (:consider_powerattack, :consider_feint, etc), two properties are defined, in the former case .powerattack_base_chance and .powerattack_eval_multiplier. These affect the base probability and effect of the dynamic consideration on the probability of carrying out some special move."}
push_base_chance#269rc#3610
push_eval_multiplier#269rc#3610.0
aliases#1rc#361{"default tactics", "tactics"}
description#1rc#361<clear>
object_size#1r#29{8160, 1298433965}
hidden_verbs#1rc#361<clear>
phelp_msg#1rc#361<clear>
weight#1rc#361<clear>
owner_verbs#1rc#361<clear>
plural_name#1rc#361<clear>
client_image#1rc#361<clear>
listening#1rc#361<clear>

Ancestry

Ancestors (nearest first): #1 root

Children: none

Call graph

calls n269_4 #269:tree_tag n20_5 #20:from_list n269_4->n20_5

Source

decide_on_action

Spec this none thisFlags rxdOwner #361Definer #269

Referenced by

none

Source

1":decide_on_action(who) => Decide on the action 'who' should take in its current battle.  Returns a list that can be passed as arguments to :queue_action, or false if no special action should be taken.";
2{who} = args;
3if ((who.fighting && who:area().combat_ok) && ($skills.brains:total(who) >= this.brains_requirement))
4enemy = who.fighting[1];
5eval_accuracy = $skills.brains:check(who, -2, 1);
6if (eval_accuracy < 0)
7random_mod = (random(abs(eval_accuracy)) - abs(eval_accuracy / 2)) * -1;
8else
9random_mod = 0;
10endif
11for consideration in (this.considerations)
12if (ret = this:("consider_" + consideration)(who, random_mod))
13return ret;
14endif
15endfor
16endif
17return 0;

consider_grab

Spec this none thisFlags rxdOwner #361Definer #269

Referenced by

none

Source

1{who, random_mod} = args;
2enemy = who.fighting[1];
3"Don't grab if we are already grabbing someone...";
4if (!valid($actions.restrain:is_restrainer(who)))
5if (who:cooldown_check("grab", 0, 0, 1) && (!enemy:is_doing($actions.struggle)))
6pot = (($skills.brawn:total(who) + $skills.reflexes:total(who)) - $skills.dodge:total(enemy)) + random_mod;
7free_hands = (who:weapon().handed < who:hands()) || (who:weapon() == who.unarmed_weapon);
8if (free_hands && ((this.grab_base_chance + toint(tofloat(pot) * this.grab_eval_multiplier)) >= random(100)))
9return {$actions.restrain, {enemy}, 1, "restrain " + enemy:name()};
10endif
11endif
12endif

consider_dodge

Spec this none thisFlags rxdOwner #361Definer #269

Referenced by

none

Source

1{who, random_mod} = args;
2if (who:cooldown_check($actions.dodge, 0, 0, 1))
3for enemy in (who.fighting)
4if (enemy.fighting && (enemy.fighting[1] == who))
5if (this.dodge_base_chance >= random(100))
6return {$actions.dodge, {}, 1, "dodge"};
7endif
8endif
9endfor
10endif

consider_push

Spec this none thisFlags rxdOwner #361Definer #269

Referenced by

none

Source

1{who, random_mod} = args;
2enemy = who.fighting[1];
3"Don't grab if we are already grabbing someone...";
4if (($actions.restrain:is_restrainer(who) == enemy) && (!`enemy.unshowable ! E_PROPNF => 0'))
5allexits = {};
6for exit in (who:room():exits())
7if (((exit.direction != "up") && (!("up" in exit.aliases))) && exit:allows_shove(enemy))
8allexits = listappend(allexits, exit);
9endif
10endfor
11drops = {};
12for exit in (allexits)
13if (is_a(exit, #12300))
14drops = listappend(drops, exit);
15endif
16endfor
17chance1 = toint(tofloat(this.push_base_chance) + (1.0 * this.push_eval_multiplier));
18chance2 = this.push_base_chance;
19if (drops && (chance1 >= random(100)))
20drop = drops[random($)];
21return {$actions.verb, {drop, "_push", {who, enemy}, 0, 1}};
22endif
23if (allexits && (chance2 >= random(100)))
24exit = allexits[random($)];
25return {$actions.verb, {exit, "_push", {who, enemy}, 0, 1}};
26endif
27endif

tree_tag

Spec this none thisFlags rxdOwner #361Definer #269

Referenced by

none

Source

1return $su:from_list(this.considerations, ",");