I have four major "problems", and with simple coding, I've fixed them. I say "problems" because not everyone might see them as problems. I'm not sure what DG would think.
And because necrotic minions all use dumb ai, even though their equivalent npcs don't all do so, these improvements improve minions quite a lot, but I've only played to early levels.
There might be some unintended consequences to my changes. One thing is clear, the starting zones are much tougher.
So the three changes are:
1. Regen infusions, healing infusions, skeleton reassemble, and conversion (solipsist) are only used if health falls below 60%
2. Archers only use reload if they have no ammo.
3. Any available talents other than plain melee Attack are used before Attack.
4. Any available talents other than shoot for archers, are used before Shoot (i.e. Pinning Shot, Crippling Shot, etc)
How is this different then? Well take the archer using dumb ai. In a non-adjacent position, currently he/she chooses between shoot and reload, at 50/50 chance of each. With my changes, it is always shoot, unless ammo = 0.
But even better, if an archer is adjacent to an enemy, it currently has three available talents, shoot, reload, and attack. changes 2 and 3 combine so that only shoot works.
And a Master Skeleton archer (e.g., one of your minions
Or take for instance a simple orc warrior, as found in Escape from Reknor. He will typically have Crush and Sunder Armour. Both will be used prior to attack. And as soon as they reset, they will be used again. And combined with 1, they are now tougher to beat.
The code is very simple, and someone might even do it better:
Code: Select all
-- Randomly use talents
newAI("dumb_talented", function(self)
	-- Find available talents
	local avail = {}
	local tx, ty = self:aiSeeTargetPos(self.ai_target.actor)
	local target_dist = core.fov.distance(self.x, self.y, tx, ty)
-- JENX ADDED - variable to check for Attack and Shoot
	local canAttack = 0
	local canShoot = 0
	for tid, _ in pairs(self.talents) do
		local t = self:getTalentFromId(tid)
--		print(self.name, self.uid, "dumb ai talents can try use", t.name, tid, "::", t.mode, not self:isTalentCoolingDown(t), target_dist <= self:getTalentRange(t), self:preUseTalent(t, true), self:canProject({type="bolt"}, self.ai_target.actor.x, self.ai_target.actor.y))
		-- For dumb AI assume we need range and LOS
		-- No special check for bolts, etc.
		local total_range = self:getTalentRange(t) + self:getTalentRadius(t)
		local tg = {type=util.getval(t.direct_hit, self, t) and "hit" or "bolt", range=total_range}
		if t.mode == "activated" and not t.no_npc_use and
		   not self:isTalentCoolingDown(t) and self:preUseTalent(t, true, true) and
		   (not self:getTalentRequiresTarget(t) or self:canProject(tg, tx, ty))
		   then
-- JENX ADDED: only use regen infusion or healing if life < 60% max life
			if t.name == "Infusion: Regeneration" or t.name == "Infusion: Healing" or t.name == "Skeleton Reassemble" or t.name == "Conversion" then
				local life = 100 * self.life / self.max_life
				if life < 60 then
					avail[#avail+1] = tid
					print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
				end
-- JENX ADDED: only use reload if ammo = 0
			elseif t.name == "Reload" then
--				print(self.name, self.uid, "ammo fix <<<<<<<<<<<<")
				local a = self:hasAmmo()
--				print(self.name, self.uid, a, a.combat.shots_left, a.combat.capacity)
				if a then
					if a.combat.shots_left == 0 then
						avail[#avail+1] = tid
						print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
					end
				end
			else
				avail[#avail+1] = tid
				print(self.name, self.uid, "dumb ai talents can use", t.name, tid)
				if t.name == "Attack" then
					canAttack = #avail
					print(self.name, self.uid, "canAttack <<<<<<<<<<<<", #avail)
				end
				if t.name == "Shoot" then
					canShoot = #avail
					print(self.name, self.uid, "canShoot <<<<<<<<<<<<", #avail)
				end
			end
		elseif t.mode == "sustained" and not t.no_npc_use and not self:isTalentCoolingDown(t) and
		   not self:isTalentActive(t.id) and
		   self:preUseTalent(t, true, true)
		   then
			avail[#avail+1] = tid
			print(self.name, self.uid, "dumb ai talents can activate", t.name, tid)
		end
	end
-- JENX ADDED - if more than one talent and attack is available, do the talent rather than attack
	if #avail > 1 and canAttack > 0 then
		table.remove(avail,canAttack)
	end
-- then remove shoot, if other (shooting?) talents available
	if #avail > 1 and canShoot > 0 then
		table.remove(avail,canShoot)
	end
--JENX end
	if #avail > 0 then
		local tid = avail[rng.range(1, #avail)]
		print("dumb ai uses", tid)
		self:useTalent(tid)
		return true
	end
end)