CaseyLoufek wrote:
The summon works perfectly except that I can only see one of them at a time.
Hah! Congratulations, that's probably the most obscure bug I've ever had reported on this project!
The problem is that each fighter is given a tag (with the 'SetTag(str)' method), which is always used as the tag passed to renpy.show() to display that fighter. (In case you're unaware: when showing, Ren'Py will replace an existing Displayable with the same tag if one exists on the screen.)
When a fighter is added to a faction in the first place, the system constructs a new tag based on the fighter name, the number of fighters in its faction, and so on... meaning that in most normal situations, it should be unique, so when a fighter is shown it will always get shown straight, and not remove anything else from the scene.
The SetTag method is called when the fighter is added to the battle via AddFighter, to ensure that a fighter which is re-used in many battles (e.g. a party member) doesn't accidentally cause a conflict with another fighter which was created just for this battle, and so on; the tag is specific to that battle.
So in the case of your skill here, this was happening:
- Make a new copy of an existing fighter
- Add new copy to whatever the current faction is - probably the last one added to the battle, and thus probably 'Enemies' or something and not the same faction as the caster; at this point the system says "how many fighters are in this faction? Oh, six?" and sets the tag of the new fighter to "Enemies_6" or something similar.
- Changes the faction of the new fighter to "Players" (or whatever) and thus reduces the number of fighters in the 'Enemies' faction to 5 again.
- ...
- Next time you add a new summon, it spawns in the 'Enemies' faction, checks how many fighters - "Oh, six?" and sets the tag of the new new fighter to "Enemies_6"...
So thus, you end up with more than one fighter with the same tag, and when each one gets shown, all the others are removed from the scene because that's a fundamental behaviour of Ren'Py!
(When ChangeFaction gets called, changing the tag is usually unnecessary, as it will have had a unique tag before the change and it'll still be unique after the change, and most of the time new fighters won't be added mid-battle.)
The most direct solution would be to call 'SetTag' on the new fighter before exiting the method:
Code: Select all
def PerformAction(self, fighter, target):
p = target[0]
self.summoned = copy.deepcopy(clyde)
fighter._battle.AddFighter(self.summoned, x=p.X, y=p.Y)
self.summoned._battle.ChangeFaction(self.summoned, fighter.Faction)
self.summoned.SetTag("summoned_" + str(self._count))
self._count = self._count + 1
This works, but it's pretty hacky. Also, if you have more than one instance of your summon skill, you could still get tag conflicts without some additional messing around... but I present the option to further understanding of the system.
A better answer is to simply set the battle's 'current' faction before adding the fighter, meaning that there's no need to change faction later and the unique tag which is generated for that fighter in AddFighter is valid:
Code: Select all
def PerformAction(self, fighter, target):
p = target[0]
self.summoned = copy.deepcopy(clyde)
fighter._battle.SetFaction(fighter.Faction)
fighter._battle.AddFighter(self.summoned, x=p.X, y=p.Y)
fighter._battle.Show()
if (self._endTurn):
fighter.EndTurn()
You'll note that I also added a call to Show() on the battle to make sure that the new fighter is shown immediately that it's added. Although realistically, if you want any kind of entrance animation it's probably better to set that one fighter's state to "summoned" or something, then back to "default" immediately afterwards - state changes will cause the fighter to be displayed, and you can then use state transitions to add an entrance animation.
Anyway, while the above fix will work in the majority of cases (you'll still have some potential problems if one of the summoned fighters gets charmed then another summoned, for example) the tag generation needs to be improved, it's a bug that it should ever generate duplicate tags whatever you've done with fighters changing sides or being added mid-fight, so I'll fix that for the next release; thanks for finding it! In case you want to fix it yourself in the meantime, the call in question is on line 406 of engine.rpy, in the AddFighter method. I'm thinking a simple increment on a battle-instance variable which gets added to the tag will be enough.
(You'll possibly also be pleased to hear that to support the new script extensions which are the next release's Big New Feature, I've added a load of 'builder' classes to the next release; so for things like your summon skill, rather than performing a deep copy you could simply pass in a FighterBuilder that you made earlier, and whenever a fighter is summoned, simply call the Build() method on that builder to get a fresh and ready-to-go instance of that fighter. I'm hoping this will be more useful than the "make me a fighter" methods which I've employed myself before (in
Tristan, for one) to spawn popcorn enemies and the like.)