Larian Banner: Baldur's Gate Patch 9
Previous Thread
Next Thread
Print Thread
Page 3 of 3 1 2 3
Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian
Well, the test I did to see that it works was as follows:
1. At the intro fight with the three skeletons, kill them all, move away from them and save.
2. Reload. New enemies have spawned on top of the corpses of the original enemies.
3. Let the new enemies move prior to killing them. Move away and save.
4. Reload. With my code above, enemies spawned at the location that the last ones dies at (not on top of the original corpses).
5. Disable the Respawn toggle. Kill the enemies, save, and then reload. They should be gone.

I suppose I still need to check if consecutive saves/reloads without killing does anything, but I expect it not to. They should be spawning a creature every time since the last generation disappears upon reload (so there is only ever 1 creature spawned per original creature).
Just got around testing your version, on save,load,save,load etc. the enemies keep respawning themselves. This is because the game doesn't recognise the %spawn anymore. You should really consider using my code for a quick fix... (I don't mind, just here to help smile )

Last edited by FromHolland; 03/09/14 12:29 PM.
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
When you say that they keep respawning themselves, do you mean that after death there are 1,2,3, etc. enemies with subsequent reloads? I can't test it at the moment to check myself.

Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian
When you say that they keep respawning themselves, do you mean that after death there are 1,2,3, etc. enemies with subsequent reloads? I can't test it at the moment to check myself.
yeh, if it does work correctly for you then my game is broken smirk

And I was thinking about how to implement an on demand respawn. You can just make a Skill that respawns everything so a player can choose to respawn after a battle if they so chooses (only 1 Skill is required then instead of 2).

Last edited by FromHolland; 03/09/14 01:09 PM.
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
Apparently there has been a big mistake about my assumptions. I have been assuming that because dead spawned enemies cease to exist upon reload, the live ones would have ceased to exist as well. Now that I think about it more, that obviously doesn't make sense.

I think that I can make mine work correctly, I just need one more check to the OnInit function to see if something has already been spawned.

Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian

I think that I can make mine work correctly, I just need one more check to the OnInit function to see if something has already been spawned.
I might be wrong, but checking is ok, but how do you un-check it if the game does not see the %spawn as a %spawn anymore if he dies...?

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
What I'm thinking is this:
1. In the OnInit function, add this part to the IF check-
IF "&c5"
IsEqual(%spawn, __Me)

And then in the OnDie(%spawn) function after the THEN
Set(%spawn, __Me)

I'm cutting out a lot of the code, but those are the important additions.
At the beginning %spawn is initialized as __Me. When it dies, %spawn is still __Me.

Upon reload, it checks the IF, sees that %spawn == __Me, and creates a spawn. In the process, it sets %spawn to the new spawned character.

If at that point the game is saved/reloaded, %spawn should still be set to the spawned character, and thus not trigger the OnInit again.

When the spawn dies, %spawn is set to equal __Me again, which will make a new spawn whenever OnInit is run again.

Edit:
I think I see now. %spawn is set to null when it reloads doesn't it? My changes above didn't work; they don't even allow a single respawn to occur.

Last edited by Rhidian; 03/09/14 03:49 PM.
Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian

Edit:
I think I see now. %spawn is set to null when it reloads doesn't it? My changes above didn't work; they don't even allow a single respawn to occur.
I also found an error (big one) with my own code, and I thought I tested it before... anyways this needs fixing, will test a couple of ideas

Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
edit:

I think I've found a new solution, testing it now
update: seems to be working, need some tweaking because you'll see the spawned characters immediately when they die. When you reload they can fight again
update 2: I've set spawned chars invisible, and visible again on reload.

this is not the cleanest solution but for now it's good enough

Code
//////////////////////////////////////////////////////////////
EVENT fightmode
ON 
	OnInit()
ACTIONS
	CharacterSetCanFight(__Me,1)
	SetVisible(__Me,1)
	
EVENT CopyTheDead
VARS
	CHARACTERTEMPLATE:_template
	FLOAT3:_MyPosition
ON 
	OnDie(__Me,_,_,_)
ACTIONS
	IF "c1&c2"
		CharacterGetTemplate(__Me,_template)
		GetPosition(__Me,_MyPosition)
	THEN
		SpawnCharacter(%Spawn,_template,_MyPosition,0)
		SetVisible(%Spawn,0)
		CharacterSetOffStage()
		CharacterSetCanFight(%Spawn,0)
	ENDIF
//////////////////////////////////////////////////////////////

Last edited by FromHolland; 03/09/14 07:49 PM.
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
I believe that I figured out what was going wrong with the code, and the new version passes all of the tests (consecutive reloads without killing, consecutive reloads with killing, killing after moving, killing with Respawn enabled/disabled).

My belief is that upon Initialization, the living characters spawned via the SpawnCharacter command are given new GUIDs. Because the scripts were storing the character after they were spawned, when it came to OnInit the stored character and the living character with a new GUID are no longer equal. Thus the %spawn variable storing the spawned character is unreliable, and can only really work so long as the game isn't reloaded.

My solution then was to focus everything around the original character's GUID, since that will always remain constant across different save reloads. I have the script set so that the spawned characters store the original character as a variable, which they can then check upon death (and manipulate so that the parent realizes they no longer have children).

Here is version 3 of the mod, which should have everything working correctly now.
http://www.mediafire.com/download/mdjb913an5t2phv/RespawningEnemiesWIPv3.zip

And the code-

Default Character changes-
Code
INIT

INT:%canRespawn=0
CHARACTER:%parent=__Me
FLOAT3:%spawnPos=null
INT:%hasChild=0


EVENTS
EVENT RespawnCharacter
VARS
CHARACTERTEMPLATE:_root
FLOAT3:_myPos
CHARACTER:_child
ON
OnInit()
ACTIONS
IF "c1&c2&c3&c4&c5"
IsEqual(%canRespawn, 1)
CharacterIsDead(__Me)
CharacterGetTemplate(__Me, _root)
GetPosition(__Me, _myPos)
IsEqual(%hasChild, 0) 
THEN
IF "c1"
IsEqual(%spawnPos, null)
THEN
Set(%spawnPos, _myPos)
ENDIF
SpawnCharacter(_child, _root, %spawnPos, 0)
SetVar(_child, "parent", __Me)
Set(%hasChild, 1)
Set(%canRespawn, 0)
ENDIF

EVENT ProgenyDeath
VARS
FLOAT3:_myPos
ON
OnDie(__Me,_,_,_)
ACTIONS
IF "!c1&c2"
IsEqual(__Me, %parent)
GetPosition(__Me, _myPos)
THEN
SetVar(%parent, "hasChild", INT:0)
SetVar(%parent, "spawnPos", _myPos)
CharacterEvent(%parent, "CheckForRespawn")
ENDIF

Note that the OnInit function is meant to be run by the original characters, while the OnDie event is meant to work for the spawned characters only.


Story code-
Code
INITSECTION
DB_RespawnEnabled(1);


KBSECTION
IF
CharacterCreationFinished(CHARACTER_NULL)
AND
CurrentLevel(_Lvl)
AND
DB_CharacterCreationLevels(_Lvl)
THEN
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnDisable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnDisable");


IF
CharacterUsedSkill(_Char, "Shout_RespawnEnable", _)
AND
DB_RespawnEnabled(0)
THEN
NOT DB_RespawnEnabled(0);
DB_RespawnEnabled(1);

IF
CharacterUsedSkill(_Char, "Shout_RespawnDisable", _)
AND
DB_RespawnEnabled(1)
THEN
NOT DB_RespawnEnabled(1);
DB_RespawnEnabled(0);

IF
CharacterDied(_Char)
THEN
CharacterSetEvent(_Char, "CheckForRespawn");

IF
CharacterEvent(_Char, "CheckForRespawn")
AND
DB_RespawnEnabled(1)
THEN
CharacterSetVarInteger(_Char, "canRespawn", 1);


Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian
I believe that I figured out what was going wrong with the code, and the new version passes all of the tests (consecutive reloads without killing, consecutive reloads with killing, killing after moving, killing with Respawn enabled/disabled).

My belief is that upon Initialization, the living characters spawned via the SpawnCharacter command are given new GUIDs. Because the scripts were storing the character after they were spawned, when it came to OnInit the stored character and the living character with a new GUID are no longer equal. Thus the %spawn variable storing the spawned character is unreliable, and can only really work so long as the game isn't reloaded.

My solution then was to focus everything around the original character's GUID, since that will always remain constant across different save reloads. I have the script set so that the spawned characters store the original character as a variable, which they can then check upon death (and manipulate so that the parent realizes they no longer have children).

Here is version 3 of the mod, which should have everything working correctly now.
http://www.mediafire.com/download/mdjb913an5t2phv/RespawningEnemiesWIPv3.zip

And the code-

Default Character changes-
Code
INIT

INT:%canRespawn=0
CHARACTER:%parent=__Me
FLOAT3:%spawnPos=null
INT:%hasChild=0


EVENTS
EVENT RespawnCharacter
VARS
CHARACTERTEMPLATE:_root
FLOAT3:_myPos
CHARACTER:_child
ON
OnInit()
ACTIONS
IF "c1&c2&c3&c4&c5"
IsEqual(%canRespawn, 1)
CharacterIsDead(__Me)
CharacterGetTemplate(__Me, _root)
GetPosition(__Me, _myPos)
IsEqual(%hasChild, 0) 
THEN
IF "c1"
IsEqual(%spawnPos, null)
THEN
Set(%spawnPos, _myPos)
ENDIF
SpawnCharacter(_child, _root, %spawnPos, 0)
SetVar(_child, "parent", __Me)
Set(%hasChild, 1)
Set(%canRespawn, 0)
ENDIF

EVENT ProgenyDeath
VARS
FLOAT3:_myPos
ON
OnDie(__Me,_,_,_)
ACTIONS
IF "!c1&c2"
IsEqual(__Me, %parent)
GetPosition(__Me, _myPos)
THEN
SetVar(%parent, "hasChild", INT:0)
SetVar(%parent, "spawnPos", _myPos)
CharacterEvent(%parent, "CheckForRespawn")
ENDIF

Note that the OnInit function is meant to be run by the original characters, while the OnDie event is meant to work for the spawned characters only.


Story code-
Code
INITSECTION
DB_RespawnEnabled(1);


KBSECTION
IF
CharacterCreationFinished(CHARACTER_NULL)
AND
CurrentLevel(_Lvl)
AND
DB_CharacterCreationLevels(_Lvl)
THEN
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnDisable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnDisable");


IF
CharacterUsedSkill(_Char, "Shout_RespawnEnable", _)
AND
DB_RespawnEnabled(0)
THEN
NOT DB_RespawnEnabled(0);
DB_RespawnEnabled(1);

IF
CharacterUsedSkill(_Char, "Shout_RespawnDisable", _)
AND
DB_RespawnEnabled(1)
THEN
NOT DB_RespawnEnabled(1);
DB_RespawnEnabled(0);

IF
CharacterDied(_Char)
THEN
CharacterSetEvent(_Char, "CheckForRespawn");

IF
CharacterEvent(_Char, "CheckForRespawn")
AND
DB_RespawnEnabled(1)
THEN
CharacterSetVarInteger(_Char, "canRespawn", 1);

then we arrived at the same conclusion smile grats m8!

Last edited by FromHolland; 03/09/14 07:55 PM.
Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
Alright, I think this mod is at the point where it is feature complete.

Version 4 of the mod-
http://www.mediafire.com/download/g7554qx0v4jd9e3/RespawningEnemiesV4.zip


Features:
-Enemies will respawn* where they last died (this is on by default)
-Player characters receive four skills upon arriving at Cyseal Beach that toggle various functions in this mod.
1. Disable Respawning Enemies - This makes it so that when enemies are killed, they no longer respawn.

2. Enable Respawning Enemies - This makes it so that enemies who are killed will respawn.

3. Mass Respawn - This makes it so that all NPCs who are currently dead (and haven't respawned) will respawn, even if they were killed when Respawn was disabled.

4. Reset Spawn Positions - The next time that dead enemies respawn will be at where they originally died at

*Respawn means that a copy of the enemy will appear where the NPC last died. The original NPC's corpse will remain in the location that they originally died at.

---
Full code-

Default Character changes:
Code
INIT

INT:%canRespawn=0
CHARACTER:%parent=__Me
FLOAT3:%spawnPos=null
INT:%hasChild=0

EVENTS
EVENT RespawnCharacter
VARS
CHARACTERTEMPLATE:_root
FLOAT3:_myPos
CHARACTER:_child
ON
OnInit()
ACTIONS
IF "c1&c2&c3&c4&c5"
IsEqual(%canRespawn, 1)
CharacterIsDead(__Me)
CharacterGetTemplate(__Me, _root)
GetPosition(__Me, _myPos)
IsEqual(%hasChild, 0) 
THEN
IF "c1"
IsEqual(%spawnPos, null)
THEN
Set(%spawnPos, _myPos)
ENDIF
SpawnCharacter(_child, _root, %spawnPos, 0)
SetVar(_child, "parent", __Me)
Set(%hasChild, 1)
Set(%canRespawn, 0)
ENDIF

EVENT ProgenyDeath
VARS
FLOAT3:_myPos
ON
OnDie(__Me,_,_,_)
ACTIONS
IF "!c1&c2"
IsEqual(__Me, %parent)
GetPosition(__Me, _myPos)
THEN
SetVar(%parent, "hasChild", INT:0)
SetVar(%parent, "spawnPos", _myPos)
CharacterEvent(%parent, "CheckForRespawn")
ENDIF

EVENT ResetSpawnPosition
VARS
FLOAT3:_myPos
ON
OnCharacterEvent(__Me, "ResetSpawnPosition")
ACTIONS
IF "c1"
GetPosition(__Me, _myPos)
THEN
Set(%spawnPos, _myPos)
ENDIF


Story script-
Code
INITSECTION
DB_RespawnEnabled(1);

KBSECTION
IF
CharacterCreationFinished(CHARACTER_NULL)
AND
CurrentLevel(_Lvl)
AND
DB_CharacterCreationLevels(_Lvl)
THEN
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player1, "Shout_RespawnDisable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnEnable");
CharacterAddSkill(CHARACTER_Player2, "Shout_RespawnDisable");
CharacterAddSkill(CHARACTER_Player1, "Shout_MassRespawnEnable");
CharacterAddSkill(CHARACTER_Player2, "Shout_MassRespawnEnable");
CharacterAddSkill(CHARACTER_Player1, "Shout_ResetSpawnPosition");
CharacterAddSkill(CHARACTER_Player2, "Shout_ResetSpawnPosition");


IF
CharacterUsedSkill(_Char, "Shout_RespawnEnable", _)
AND
DB_RespawnEnabled(0)
THEN
NOT DB_RespawnEnabled(0);
DB_RespawnEnabled(1);

IF
CharacterUsedSkill(_Char, "Shout_RespawnDisable", _)
AND
DB_RespawnEnabled(1)
THEN
NOT DB_RespawnEnabled(1);
DB_RespawnEnabled(0);

IF
CharacterDied(_Char)
THEN
CharacterSetEvent(_Char, "CheckForRespawn");

IF
CharacterEvent(_Char, "CheckForRespawn")
AND
NOT _Char.isPlayer()
AND
DB_RespawnEnabled(1)
THEN
CharacterSetVarInteger(_Char, "canRespawn", 1);

IF
CharacterDied(_Char)
AND
NOT _Char.isPlayer()
AND
NOT DB_DeadCharacters(_Char)
THEN
DB_DeadCharacters(_Char);

IF
CharacterEvent(_Char, "CheckForRespawn")
AND
NOT DB_DeadCharacters(_Char)
THEN
DB_DeadCharacters(_Char);

IF
CharacterUsedSkill(_Char, "Shout_MassRespawnEnable", _)
THEN
MassRespawn();

PROC
MassRespawn()
AND
DB_DeadCharacters(_Char)
THEN
CharacterSetVarInteger(_Char, "canRespawn", 1);
NOT DB_DeadCharacters(_Char);
MassRespawn();

IF
CharacterDied(_Char)
AND
NOT DB_SpawnPositions(_Char)
THEN
DB_SpawnPositions(_Char);

IF
CharacterEvent(_Char, "CheckForRespawn")
AND
NOT DB_SpawnPositions(_Char)
THEN
DB_SpawnPositions(_Char);

IF
CharacterUsedSkill(_Char, "Shout_ResetSpawnPosition", _)
THEN
MassResetSpawnPosition();

PROC
MassResetSpawnPosition()
AND
DB_SpawnPositions(_Char)
THEN
CharacterSetEvent(_Char, "ResetSpawnPosition");
NOT DB_SpawnPositions(_Char);
MassResetSpawnPosition();



Lessons learned from working on this mod-

1. Main campaign charScripts (and presumably itemScripts) can be overwritten by mods. There might be some side effects, but it can be done.

2. Story scripts and charScripts/itemScripts can work together to great effect.

3. Resurrected characters don't give exp but are easier to work with, while Spawned characters give exp and are much harder to work with. Something about living spawned characters (perhaps GUID) appears to change whenever the game is loaded (or perhaps they die) such that they are no longer equal to what they were prior to game load/death.


I think I now have enough experience in charScripts/itemScripts to add a section to my tutorial thread.

Last edited by Rhidian; 03/09/14 10:30 PM.
Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
great fix :), and great mod. Somehow I'm unable to catch the spawned characters in any of my story scripts, but I can catch them in charscripts. Am I missing something...?

Joined: Jul 2014
R
Rhidian Offline OP
addict
OP Offline
addict
R
Joined: Jul 2014
I wasn't able to catch spawned characters in Story scripts either, which is why I focused everything around the spawning character (original character). The spawned enemies don't trigger CharacterDied events at the very least.

The reason charScripts might work over Story scripts is due to either the spawned character using a charScript themselves or because it matters more for AI in combat since it allows them to be targetted.

Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Originally Posted by Rhidian
I wasn't able to catch spawned characters in Story scripts either, which is why I focused everything around the spawning character (original character). The spawned enemies don't trigger CharacterDied events at the very least.

The reason charScripts might work over Story scripts is due to either the spawned character using a charScript themselves or because it matters more for AI in combat since it allows them to be targetted.
Yeh sadly there is no way I can think of (and I tried many smile ) to catch them in story scripts. It would be great though to create and manipulate characters on the fly, like for some RTS element that I'm working on in my own mod. Will shelf that idea sadly.

edit: when I create a character template and then remove the original template from the game(ie destroychar), the new character is recognised by story scripting as if it where the original one.

Last edited by FromHolland; 07/09/14 02:26 PM.
Joined: Sep 2014
apprentice
Offline
apprentice
Joined: Sep 2014
I would love to see this project completed. Personally, I see the current status quo of a fixed number of objects in the world as problematic for two key reasons.

In gameplay terms, it means that I feel a need to kill every single monster, and gainfully utilise every single item.

In feel/realism, the game becomes considerably less... alive once you've been playing a while. Hey, tell Aureus he can have a holiday, there is not a single living corpse remaining in the Cyseal area.

For the same reason, I'd love to see ores respawn, and further chances to pickpocket: but uh, for difficulty, perhaps not further copies of every painting, plate, and cup (without substantial balancing). My, my, the Cyseal art and homewares scene is booming.

Do you have plans to remove corpses at some point? I imagine the games engine could get pretty overloaded otherwise (if an area is cleared enough times).

edit: I guess I should pause to note there are some nice advantages in D:OS relative to the traditional fully respawning world, it's really nice being able to set up camp wherever you like, set up your chests in places, take over abandoned buildings, and not worry about "safe storage". Perhaps there's a best of both worlds though? smile

Last edited by synra; 07/09/14 06:04 PM.
Joined: Jul 2014
journeyman
Offline
journeyman
Joined: Jul 2014
Rhidian finished this mod, only the original corpse remains and the newly spawned characters do not leave corpses

Joined: Sep 2014
apprentice
Offline
apprentice
Joined: Sep 2014
It appears I'm behind the times. That sounds like an excellent solution. I may just have to overcome caution and dig in smile

Joined: Jan 2015
H
stranger
Offline
stranger
H
Joined: Jan 2015
Hi all, how to install this RespawningEnemiesV4.zip mod on OS X?

Page 3 of 3 1 2 3

Link Copied to Clipboard
Powered by UBB.threads™ PHP Forum Software 7.7.5