Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

BUG: Adaptive Familiar next to another Adaptive Familiar doesn’t get stats, when the first adaptive familiar gets stats from an adjacent follower.

(+1)

Yes. Sadly familiar will not trigger other familiars. Technical constraint.

That sounds interesting. Can you roughly explain the cause of that constraint, as I’m also interested in developing card game rogue-likes.

(+1)

How familiar works is that whenever a status (e.g. a buff that gives +1/+1) is given to an adjacent follower, a hidden status on the said follower will then transfer a copy of that status to familiar. However, the status being transfered can't remember what's going on before the transfer. Therefore, if we let a status being able to be transfered multiple time, it'll result in an infinite loop of 2 familiars transferring to same status to each other (since the status can't remember that the prior incarnation of itself has already being transfered to one of the familiar). So we just make it so that a transfered status can't be transfered again.

(5 edits)

I’ve not even considered the possibility of an infinite loop. Every follower could remember from whom he’s gotten stats within “A stat propagation iteration” and not gain stats, when he has already gotten stats from that follower this iteration. That would in my example lead to the following:

// Follower object structure:
//   First  element: is the identifier for a specific follower
//   Second element: follower stats after stat gain has been applied
//   Third  element: a list of followers this follower has gotten stats from (this stat propagation iteration)
// The Templar0 just attacked.
[Templar0 2/1 []] --(Templar0 +1/+0)-->
  [Familiar0 3/2 [Templar0]] --(Familiar0 +1/+0)-->
    [Familiar1 3/2 [Familiar0]] --(Familiar1 +1/+0)-->
      [Familiar0 4/2 [Templar0 Familiar1]] --(Familiar0 +1/+0)-->X
        [Familiar1 3/2 [Familiar0]]

Seems reasonable to me.
(+2)

Yes, except that that's not how status works in this game at all. To get into more details, almost all interactions in the game is done through "signals", and each follower will have a bunch of "status" to interact with those signals. Each signal is consisting of a signal type, whatever object reference required from that signal type, and a bunch of float variable. for example, a signal can be something like "deal 3 damage" or "gain +1/+1"; "deal 3 damage" signal will have the signal type of "damage" with variable "damage = 3"; "gain +1/+1" signal will have the signal type of "create status", with a reference to a generic stat status, and variable "AddDamage = 1; AddLife = 1". Each status can be more complicated; some status will passively modify a follower's stats or have interaction with specific signals, like the status "this follower will gain double stats"; How signal and status works in action is: when a follower receive the "gain +1/+1" signal, the signal will inform all status on that follower of the signal's existence, and if the follower has the "this follower will gain double stats" status, the status will then modify the "AddDamage = 1; AddLife = 1" variables of the signal to "AddDamage = 2; AddLife = 2"; after that, the signal will execute its proper function to add a new generic stat status to the follower, and modify the new status base on the AddDamage and AddLife variables; maybe the follower also have a status that says "deal 3 random damage on stats gain" status, in which case, when the status is aware of the "gain +1/+1" signal, it will send another signal "deal 3 random damage" to the same follower, which will then go through this entire process again.

How familiar works is that it'll create a special "adjacent stat status link" status to all followers before the start of combat. This adjacent stat status link is a status that, whenever the source follower receives a "create status" signal, the status will check whether the "create status" signal is creating a stat status, whether the "create status" signal can be interacted by status (whether it has "IgnoreTrigger = 1"), whether the source follower is adjacent to the follower that created the status link (the caster, which, in this case, should be a familiar), and whether the caster is alive. If all conditions are met, the status link will then force another copy of the status are to be created by "create status" signal to the caster. And here's the problem. If the status link then create a new "create status" signal and send it to the caster, then that new signal will also go through the same process. That means that if 2 familiars each have created a status link on each other, then familiar 1 will gain a stat status and send "create status" signal to familiar 2, which will go through the same process and end up sending a copy of the same "create status" signal to familiar 1. To avoid this, the "create status" signal sent from familiar 1 to familiar 2 will need to include the information that "this signal is created by a status link from familiar 1, and therefore should not trigger any other status link that are created by familiar 1", which is really troublesome to implement because signals are coded to only carry float variables and not extra reference to objects. What we end up doing is to just mark the new create status signal with "IgnoreTrigger", making it unable to interact with other status link status.

I guess this is just a really complicated way to say that yes, such a propagation iteration does make sense in a vacuum, but it doesn't really work with the process of how all signals and status are processed in this game. To make familiar being able to trigger other familiar, we'll need to change how signal or status are coded, which is just a bit over-scoped at the moment.

(4 edits)

[…], the signal will execute its proper function to add a new generic stat status to the follower, and modify the new status base on the AddDamage and AddLife variables;

So a temporary status.

From what I gather a status is immutable. The “Ignore Trigger” is part of the signal creation interface, which is outside and doesn’t have a slot for “follower, who emitted this signal”. Even if the issue of ordering the status was solved, adding a status to the front, which creates a ton of new status to somehow track who got a “gain +x/+x” from whom, drives the system ad absurdum and creates some kind of cumbersome meta abstraction, which is beyond hacky. That’s asking for some functional programming big-brainism, which is probably waaaaaaaaaay out of scope as you said.

Thanks for the in depth explanation.

This game is really inspiring and by far the game I’ve played most on itch.

Also, a typo :D :

the status link will then force another copy of the status ~~are~~ to be created by “create status” signal to the caster.

P.S. A funny build that managed to reach level 58: