Jump to content

How to detect multiple copies of the same creature?


argent77

Recommended Posts

For some time now I'm running into this problem and I haven't found a solution for so far.

 

Describing my problem is somewhat complicated, but I'll try it anyway:

In the mod I'm currently working on I am using helper creatures to run "global" scripts as a way to avoid polluting the baldur.bcs. So each time the party enters a new area, a helper creature is created (if it doesn't yet exist). However, the game doesn't limit the execution of scripts to the current area only. Oftentimes scripts from related areas are executed too. That has probably something to do with master areas and how they control script execution (I don't understand this mechanism fully yet). I can detect this case too, by using Exists() as one of the triggers to decide whether to create a new helper creature.

 

However, if I save and reload a game, the scripts from the related areas aren't executed anymore and as a result a new helper creature is created in the current area. But if I visit the former areas again, then two or more helper creatures are active which could lead to multiple executions of the same script block in special situations. I'm trying to prevent it as best I can, but it doesn't always work.

 

This leads to my question:

Is it possible to detect whether two or more helper creatures are active at the same time, so that I can disable the other one(s)?

Link to comment

InMyArea([PC]) seems to work only if a party member is in visual range of the helper creature. Changing it into InMyArea(Player1) helps a bit, at least in this regard, but the helper creature will spawn and destroy itself in an endless cycle whenever I enter certain areas and I don't know why.

Link to comment

There isn't much code involved. The helper creatures are spawned by a very simple script block in the baldur[25].bcs:

IF
   // Checking for any active creature of the given name, no matter where it is located
   !Exists("A7AFQCTL")
THEN RESPONSE #100
   // Creature is placed into the upper left corner of the current map, regardless of obstacles
   CreateCreatureImpassableAllowOverlap("A7AFQCTL", [0.0], 0)
   Continue()
END

The creature is as unobtrusive as possible. I'm using a bird animation ID to avoid blocking anyone's path and all kinds of opcode effects to make it undetectable and indestructible. I've also applied opcodes #293 (Offscreen AI) and #310 (Protection from Timestop) to ensure that its scripts are executed all the time.

 

First I've tried to add the following block into the creature script:

IF
   !InMyArea([PC])
THEN RESPONSE #100
   DestroySelf()
END

However, this code doesn't work correctly and destroys the creature immediately after it has been created, which in turn triggers the baldur.bcs code to spawn a new creature and so forth. It only works as expected if a party member is in visual range of the creature.

 

Changing it into

IF
   !InMyArea(Player1)
   !InMyArea(Player2)
   !InMyArea(Player3)
   !InMyArea(Player4)
   !InMyArea(Player5)
   !InMyArea(Player6)
THEN RESPONSE #100
   DestroySelf()
END

solves the former problem somewhat. Now I'm running into this problem only when I enter certain areas. It happens, for example, when I enter Gaelan Bayle's home (AR0311) or many other buildings. However, it doesn't happen when I enter the 'Copper Coronet' (AR0406) or moving to one of the other main city areas. I'm not sure what is causing this behavior.

Link to comment

Is the creating the creature really best done in the baldur.bcs file ? What is the creature / helper for ? For example a spell can create the helper creature and let the actions to be done and then it's over... there is not many cases where a constant helper is actually required in every area at least. And in my case you can use this:

IF
!InMyArea(LastSummonerOf(Myself))
THEN
 RESPONSE #100
DestroySelf()
END 

Link to comment

Unfortunately I need it almost all the time during the whole game.

 

The script executed by the helper creature is mainly used to let a character who is accompanying the party die or transform in a controlled manner whenever the HP is low. I can't do it in the character script itself, because it doesn't always run (e.g. when confused, stunned or panicked) or it takes too long for the script block to fire (that's especially true in the heat of battle).

I'm also using it for a couple of other things which are hard to place somewhere else. The only alternative I can think of is using the baldur.bcs directly. ;)

 

The probability that two or more instances of the same script block are executed at the same time is very small. I've managed to trigger it only once, and that was a test run where dozens of helper creatures were present at the same time. I just want to be on the safe side.

Link to comment
The script executed by the helper creature is mainly used to let a character who is accompanying the party die or transform in a controlled manner whenever the HP is low.

Why wouldn't something like 0x4012 HPLT(O:Object*,I:Hit Points*) checked via baldur.bcs not been enough? The helper creature could then be spawned via baldur.bcs near your NPC, perform whatever it is supposed to, and DestroySelf() afterwards.
Link to comment

That's a good idea. It will solve only one problem however. I've only mentioned it briefly in my previous post, but I would also have to relocate a bunch of scripts which monitor the equipped state of a certain cursed item for all party members. This includes 18 script blocks at the moment and I haven't found a better way to implement it yet. But maybe there is a way when I study the effect opcode list again.

Link to comment
I'm also using it for a couple of other things which are hard to place somewhere else. The only alternative I can think of is using the baldur.bcs directly. ;)
And when someone places an always true condition to the begining of your baldur.bcs your script addition will never-ever take action. Say like another helper creature installed after yours is.
Link to comment
I'm also using it for a couple of other things which are hard to place somewhere else. The only alternative I can think of is using the baldur.bcs directly. ;)
And when someone places an always true condition to the begining of your baldur.bcs your script addition will never-ever take action. Say like another helper creature installed after yours is.

Luckily you can always place a Continue() at the end of your code blocks. Then even an always true condition works together with everything else.

 

 

I would also have to relocate a bunch of scripts which monitor the equipped state of a certain cursed item for all party members. This includes 18 script blocks at the moment and I haven't found a better way to implement it yet. But maybe there is a way when I study the effect opcode list again.

Well, I have found way to solve the problem of the 18 script blocks in a very efficient way, at least theoretically. There is only a minor problem which has to be addressed first. I need to apply a delayed spell effect to a creature which isn't dispellable in any way (not even by Ctrl+R). I can rule out the timing modes 4 (Delayed) and 5 (Delayed unsaved) already, because they are affected by the Ctrl+R cheat. Does anyone has another idea?

Link to comment
Luckily you can always place a Continue() at the end of your code blocks. Then even an always true condition works together with everything else.
On some and everyones elses code... you can't preemptivelly do that.

I am not saying you can't do this, I an saying you should really hard think of the consequencies of every line in that file. It's already used say 100000 times in a large megamoded game.

You might seek better options like say adding just one action to the baldur.bcs,

  IF
   Global("Activation_variable","GLOBAL",1)
   Dead("yourcres_deadvariable")
 THEN
   RESPONSE #100
   SetGlobal("Activation_variable","GLOBAL",0)
 ActionOverride(Player1,CreateItem("resummonitem",1,0,0))
  Continue()
 END 

 

Well, I have found way to solve the problem of the 18 script blocks in a very efficient way, at least theoretically.
Are you using an OR(18) or the like, cause the script will then recheck the following or was it the preseeding... conditions 16 times, which is not that effective. Yes, it shortend the code, not the actions.
Link to comment
Luckily you can always place a Continue() at the end of your code blocks. Then even an always true condition works together with everything else.
On some and everyones elses code... you can't preemptivelly do that.

I am not saying you can't do this, I an saying you should really hard think of the consequencies of every line in that file. It's already used say 100000 times in a large megamoded game.

Yes. I've seen the mess when I created a test installation of a BWS game some time ago. From a quick glance I would say that 90% of the code additions could be removed from the baldur.bcs and added somewhere else.

 

You might seek better options like say adding just one action to the baldur.bcs,

  IF
Global("Activation_variable","GLOBAL",1)
Dead("yourcres_deadvariable")
 THEN
RESPONSE #100
   SetGlobal("Activation_variable","GLOBAL",0)
 ActionOverride(Player1,CreateItem("resummonitem",1,0,0))
  Continue()
 END 

It's not as simple as that. I'm controlling a djinni with my code. Depending on his HP he either transforms into a gaseous cloud to regenerate or returns into his magical lamp using a nice special effect, but he never dies. This gives me an idea however. Maybe I could spawn the helper creature from within the djinni script. I need to test this.

 

 

Well, I have found way to solve the problem of the 18 script blocks in a very efficient way, at least theoretically.
Are you using an OR(18) or the like, cause the script will then recheck the following or was it the preseeding... conditions 16 times, which is not that effective. Yes, it shortend the code, not the actions.

No, it can be reduced to a tiny two code blocks script if I summon a helper creature by a delayed spell effect. The target specifier LastSummonerOf(Myself) helps tremendously in this case. In my current implementation I'm using three code blocks for each party member (when equipping, unequipping and executing a curse after a specific time period). The only problem is how to prevent the delayed spell effect from being dispelled.

Link to comment
It's not as simple as that. I'm controlling a djinni with my code. Depending on his HP he either transforms into a gaseous cloud to regenerate or returns into his magical lamp using a nice special effect, but he never dies. This gives me an idea however. Maybe I could spawn the helper creature from within the djinni script. I need to test this.
Well, the character does never die in the above case either... tehnically it does, but so what.

 

And the gasious form, you could do that via dialog that tells the djinn to return to gasiuos form and how long to stay at it(which determines the effects of the command).

Link to comment

I have found an alternative way now to spawn my helper creatures without using the baldur.bcs in any way. The creature script of the djinni will spawn the helper creature whenever necessary and the helper creature will destroy itself if the djinni has returned into his lamp. That way I will (hopefully) also reduce the number of helper creatures active at the same time.

It's not a perfect solution, but I don't think I can do much better with the limited capabilities of the Infinity Engine.

Link to comment

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...