Page 1 of 1

Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 1:26 pm
by helminthauge
the talent description is:

Code: Select all

The connection between predator and prey allows you to speak to the mind of your target and beckon them closer. For %d turns, they will try to come to you, even pushing others aside to do so. They will move towards you instead of acting %d%% of the time, but can save verses Mindpower to slow the effect. If they take significant damage, the beckoning may be overcome altogether. The effect makes concentration difficult for your target, reducing Spellpower and Mindpower by %d until they reach you. The Spellpower and Mindpower reduction increases with your Willpower.
which sounds like they will lose actions, just like when they're confused (but instead of acting randomly, they'll approach you).

but I see no action loss in the code of Beckoned effect. I'm not good at coding at all, so here is this topic.

Re: Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 3:21 pm
by Cathbald
Moving use energy so they do lose an action doing it.
Even better if they're slow/stunned as well they'll lose even more. And if you've both stunned AND slowed them and they move, enjoy your 10 turns of bashing them without retaliation !

Re: Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 3:36 pm
by helminthauge
ok, I should have posted the code of the Beckoned effect.
it uses mod.class.NPC.move function to move the target, which I haven't found in the code, but according to my test, it does not use energy.

Re: Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 3:38 pm
by Cathbald
Get beckoned, you'll see if you don't get double turned :P
If the question is what part of the code use up the energy, yeah, post it because I'm on phone and reading code on it is a pain ^^

Re: Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 3:42 pm
by helminthauge

Code: Select all

newEffect{
	name = "BECKONED", image = "talents/beckon.png",
	desc = "Beckoned",
	long_desc = function(self, eff)
		local message = ("The target has been beckoned by %s and is heeding the call. There is a %d%% chance of moving towards the beckoner each turn."):format(eff.src.name, eff.chance)
		if eff.spellpowerChangeId and eff.mindpowerChangeId then
			message = message..(" (spellpower: %d, mindpower: %d"):format(eff.spellpowerChange, eff.mindpowerChange)
		end
		return message
	end,
	type = "mental",
	subtype = { dominate=true },
	status = "detrimental",
	parameters = { speedChange=0.5 },
	on_gain = function(self, err) return "#Target# has been beckoned.", "+Beckoned" end,
	on_lose = function(self, err) return "#Target# is no longer beckoned.", "-Beckoned" end,
	activate = function(self, eff)
		eff.particle = self:addParticles(Particles.new("beckoned", 1))

		eff.spellpowerChangeId = self:addTemporaryValue("combat_spellpower", eff.spellpowerChange)
		eff.mindpowerChangeId = self:addTemporaryValue("combat_mindpower", eff.mindpowerChange)
	end,
	deactivate = function(self, eff)
		if eff.particle then self:removeParticles(eff.particle) end

		if eff.spellpowerChangeId then
			self:removeTemporaryValue("combat_spellpower", eff.spellpowerChangeId)
			eff.spellpowerChangeId = nil
		end
		if eff.mindpowerChangeId then
			self:removeTemporaryValue("combat_mindpower", eff.mindpowerChangeId)
			eff.mindpowerChangeId = nil
		end
	end,
	on_timeout = function(self, eff)
	end,
	do_act = function(self, eff)
		if eff.src.dead then
			self:removeEffect(self.EFF_BECKONED)
			return
		end
		if not self:enoughEnergy() then return nil end

		-- apply periodic timer instead of random chance
		if not eff.timer then
			eff.timer = rng.float(0, 100)
		end
		if not self:checkHit(eff.src:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
			eff.timer = eff.timer + eff.chance * 0.5
			game.logSeen(self, "#F53CBE#%s struggles against the beckoning.", self.name:capitalize())
		else
			eff.timer = eff.timer + eff.chance
		end

		if eff.timer > 100 then
			eff.timer = eff.timer - 100

			local distance = self.x and eff.src.x and core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) or 1000
			if math.floor(distance) > 1 and distance <= eff.range then
				-- in range but not adjacent

				-- add debuffs
				if not eff.spellpowerChangeId then eff.spellpowerChangeId = self:addTemporaryValue("combat_spellpower", eff.spellpowerChange) end
				if not eff.mindpowerChangeId then eff.mindpowerChangeId = self:addTemporaryValue("combat_mindpower", eff.mindpowerChange) end

				-- custom pull logic (adapted from move_dmap; forces movement, pushes others aside, custom particles)

				if not self:attr("never_move") then
					local source = eff.src
					local moveX, moveY = source.x, source.y -- move in general direction by default
					if not self:hasLOS(source.x, source.y) then
						local a = Astar.new(game.level.map, self)
						local path = a:calc(self.x, self.y, source.x, source.y)
						if path then
							moveX, moveY = path[1].x, path[1].y
						end
					end

					if moveX and moveY then
						local old_move_others, old_x, old_y = self.move_others, self.x, self.y
						self.move_others = true
						local old = rawget(self, "aiCanPass")
						self.aiCanPass = mod.class.NPC.aiCanPass
						mod.class.NPC.moveDirection(self, moveX, moveY, false)
						self.aiCanPass = old
						self.move_others = old_move_others
						if old_x ~= self.x or old_y ~= self.y then
							game.level.map:particleEmitter(self.x, self.y, 1, "beckoned_move", {power=power, dx=self.x - source.x, dy=self.y - source.y})
						end
					end
				end
			else
				-- adjacent or out of range..remove debuffs
				if eff.spellpowerChangeId then
					self:removeTemporaryValue("combat_spellpower", eff.spellpowerChangeId)
					eff.spellpowerChangeId = nil
				end
				if eff.mindpowerChangeId then
					self:removeTemporaryValue("combat_mindpower", eff.mindpowerChangeId)
					eff.mindpowerChangeId = nil
				end
			end
		end
	end,
	do_onTakeHit = function(self, eff, dam)
		eff.resistChance = (eff.resistChance or 0) + math.min(100, math.max(0, dam / self.max_life * 100))
		if rng.percent(eff.resistChance) then
			game.logSeen(self, "#F53CBE#%s is jolted to attention by the damage and is no longer being beckoned.", self.name:capitalize())
			self:removeEffect(self.EFF_BECKONED)
		end

		return dam
	end,
}
ok, here we go.
and I personally never remember losing actions when beckoned and forced to move (well, this may also be because those cursed were so weak that double-turned made few difference lol), and I remember moving 2 tiles toward that cursed when beckoned with just 1 click.

Re: Does Beckon cause enemies to lose actions?

Posted: Mon Sep 02, 2019 11:40 pm
by HousePet
mod.class.NPC.moveDirection(self, moveX, moveY, false) calls actor:move, which then deducts Energy for the move action.

Re: Does Beckon cause enemies to lose actions?

Posted: Tue Sep 03, 2019 1:54 pm
by Snarvid
helminthauge wrote: and I personally never remember losing actions when beckoned and forced to move (well, this may also be because those cursed were so weak that double-turned made few difference lol), and I remember moving 2 tiles toward that cursed when beckoned with just 1 click.
I sure do. I've been obliterated without a chance to respond due to bad luck vs. Beckon.

Re: Does Beckon cause enemies to lose actions?

Posted: Thu Sep 05, 2019 4:01 pm
by helminthauge
confirmed, positive.