Playing Hide And Seek With A Disappearing Npc

Post » Fri May 27, 2011 3:37 am

Ok, it's not quite broken, but I'm hitting the wall up against the limitations of the CellChanged function. I'm at a complete loss here. I've mucked around with this script for over four hours and I can't get it to work properly. Once uvi_meiree_vampire == 1, the npc is supposed to appear in different parts of the tower according to the time of day.

Begin Uvi_MeireeScriptShort NoLoreShort FirstGreetingShort doOnceShort RandShort facefixShort VampWanderShort TestVarShort TeleportIf ( servant_meiree_sweeper->GetHealth <= 0 )	If ( GetDisabled == 0 )		Disable	Endif	ReturnEndifIf ( doOnce == 0 )	If ( GetItemCount emb_memitem_mychilde > 0 )		Set TestVar to 1		Set uvi_meiree_vampire to 1		Set doOnce to 1	Elseif ( doOnce == 1 )		If ( uvi_meiree_vampire == 0 )			AiWander 256 5 0 40 20 10 0 20			PositionCell -724 -102 -256 0 "Tel Uvirith, Servant's Quarter"			Set VampWander to 0			Set doOnce to -1		Endif	EndifEndifIf ( VampWander == 0 )	If ( GetForceSneak == 1 )		ClearForceSneak	Endif	If ( GetSpell Uvi_comp_lev == 1 )		RemoveSpell Uvi_comp_lev	Endif	If ( GetSpell uvi_half_chameleon == 1 )		RemoveSpell uvi_half_chameleon	Endif	Set VampWander to -1Elseif ( VampWander == 1 ) ;levitating	If ( GetForceSneak == 1 )		ClearForceSneak	Endif	If ( GetSpell Uvi_comp_lev == 0 )		AddSpell Uvi_comp_lev	Endif	If ( GetSpell uvi_half_chameleon == 1 )		RemoveSpell uvi_half_chameleon	Endif	Set VampWander to -1Elseif ( VampWander == 2 ) ;sneaking	If ( GetForceSneak == 0 )		ForceSneak	Endif	If ( GetSpell Uvi_comp_lev == 1 )		RemoveSpell Uvi_comp_lev	Endif	If ( GetSpell uvi_half_chameleon == 0 )		AddSpell uvi_half_chameleon	Endif	Set VampWander to -1EndifIf ( uvi_meiree_vampire == 1 )	If ( facefix == 1 )	;fixes disappearing head issue		Equip uvi_helm_dummy		RemoveItem uvi_helm_dummy 1		Set facefix To 0		Return	EndIfElse	If ( VampWander > 0 )		Set VampWander to 0	EndifEndifIf ( GetCurrentAiPackage > 1 )	Set VampWander to 0	ReturnEndifIf ( CellChanged == 1 )	If ( uvi_meiree_away == 1 )		Enable		set facefix to 1		Return	Endif	If ( uvi_meiree_vampire == 0 )		If ( GameHour >= 18 )			Enable		Elseif	( GameHour <= 6 )			Enable		Else			Disable		Endif		Return	Elseif ( uvi_meiree_vampire == 1 )		Enable		Set facefix to 1		If ( uvi_meiree_away == -1 )			AiWander 256 5 0 40 20 10 0 20 0 0 0 0			PositionCell -724 -102 -256 0 "Tel Uvirith, Servant's Quarters"			Set VampWander to 0			Set uvi_meiree_away to 1			Return		Endif		Set Teleport to 1	EndifEndifIf ( Teleport == 1 )	Set Rand to Random 100	If ( Gamehour >= 21 )		Set TestVar to 2		AiWander 1024 5 0 0 10 40 0 10 0 20 0 0		If ( Rand >= 90 )			PositionCell 1104 52 28 270 "Tel Uvirith, Tower Lower"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 80 )			PositionCell 799 -31 1095 0 "Tel Uvirith, Tower Upper"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 70 )			PositionCell 4292 -1065 -1011 0 "Tel Uvirith, Tower Dungeon"			Set VampWander to 2 ;sneaking		Elseif ( Rand >= 60 )			PositionCell 2028 195 -912 0 "Tel Uvirith, Tower Dungeon"			Set VampWander to 2 ;sneaking		Elseif ( Rand >= 50 )			PositionCell 4719 4207 -1679 100 "Tel Uvirith Dungeon, Deep Tunnels"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 30 )			PositionCell 3183 3899 -2259 180 "Tel Uvirith Dungeon, Deep Tunnels"			Set VampWander to 0		Elseif ( Rand >= 0 )			PositionCell 79 181 317 180 "Tel Uvirith, Tower Lower"			Set VampWander to 0		Endif	Elseif ( GameHour <= 5 )		Set TestVar to 3		AiWander 1024 5 0 0 10 40 0 10 0 20 0 0		If ( Rand >= 90 )			PositionCell 1104 52 28 270 "Tel Uvirith, Tower Lower"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 80 )			PositionCell 799 -31 1095 0 "Tel Uvirith, Tower Upper"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 70 )			PositionCell 4292 -1065 -1011 0 "Tel Uvirith, Tower Dungeon"			Set VampWander to 2 ;sneaking		Elseif ( Rand >= 60 )			PositionCell 2028 195 -912 0 "Tel Uvirith, Tower Dungeon"			Set VampWander to 2 ;sneaking		Elseif ( Rand >= 50 )			PositionCell 4719 4207 -1679 100 "Tel Uvirith Dungeon, Deep Tunnels"			Set VampWander to 1 ;levitating		Elseif ( Rand >= 30 )			PositionCell 3183 3899 -2259 180 "Tel Uvirith Dungeon, Deep Tunnels"			Set VampWander to 0		Elseif ( Rand >= 0 )			PositionCell 79 181 317 180 "Tel Uvirith, Tower Lower"			Set VampWander to 0		Endif	Else		Set TestVar to 4		AiWander 256 5 0 40 20 10 0 20		PositionCell -724 -102 -256 0 "Tel Uvirith, Servant's Quarter"		Set VampWander to 0	Endif	Set Teleport to 0EndifEnd


Now my problem is mainly with the CellChanged function. It seems to only move the npc if you are entering the cell, not exiting it. In order to get her to move, I need to leave the cell and re-enter it before she will do it. This is not optimal. I need her to move when I leave. I had also considered using GetDistance, but that would only end up with her vanishing before you get close to her in that cell, so you would probably never see her again. Is there any better way of doing this?
User avatar
natalie mccormick
 
Posts: 3415
Joined: Fri Aug 18, 2006 8:36 am

Post » Fri May 27, 2011 8:34 am

Problem is that since the script is (I suppose) attached to the NPC, it doesn't run when you're not in the same cell with that NPC. If you want him to appear in various places regardless of whether PC is around or not, you should handle the teleporting part not in his own script but in a global or attached to an activator placed somewhere outdoors or in some other cell that PC can hardly avoid when visiting the area.
User avatar
Stryke Force
 
Posts: 3393
Joined: Fri Oct 05, 2007 6:20 am

Post » Fri May 27, 2011 7:39 am

In your script, there's a bit here that should never happen:
If ( doOnce == 0 )	If ( GetItemCount emb_memitem_mychilde > 0 )		Set TestVar to 1		Set uvi_meiree_vampire to 1		Set doOnce to 1	Elseif ( doOnce == 1 )  ;this should never happen, since it won't run unless doOnce=0		If ( uvi_meiree_vampire == 0 )			AiWander 256 5 0 40 20 10 0 20			PositionCell -724 -102 -256 0 "Tel Uvirith, Servant's Quarter"			Set VampWander to 0			Set doOnce to -1		Endif	EndifEndif


For the cellchanged issue - is there really any need to move the NPC when the player leaves? I mean, couldn't you just move them when the player comes back, as soon as the cell loads?
User avatar
Shaylee Shaw
 
Posts: 3457
Joined: Wed Feb 21, 2007 8:55 pm

Post » Fri May 27, 2011 11:44 am

Thanks for catching that Melian. I was up a bit too late last night working on that thing. ;)

It's mainly an immersion issue. Having her leave only when the player re-enters the area means that she may completely disappear and not be spotted anywhere else for a long time, because she ends up wandering into some of the lesser used areas, and if the player tells her to stop messing around and go back to her quarters, she's kind of expected to show up there. I'm ok with her vanishing for a while in most cases, but that last one, which is checked by the global uvi_meiree_away is a case where I may want to move her by other means.

Now that I've slept on the problem, and thanks to Kir's suggestion, I think I've come up with one or two ways to solve that. I could either use the GetDistance check, because uvi_meiree_away is set in dialogue, and have her leave as soon as the player is a few feet away after telling her to leave, or place one activator in her quarters that will warp her back as soon as the player enters her quarters, so that she'll be found there when she's expected to be there (and she's behind a door in that cell, so the player won't see her appear).

I think the latter option might be the way to go, but there's only one issue. If the 72 hour cleanup has cleared her data, won't it crash the game if she's warped into the same cell as the player without her being previously loaded? And can checking "corpses persist" prevent this?

The rest of the appearances can remain unpredictable. I'm quite fine with that. :)

Edit: Another problem I noticed with CellChanged is that if you put too many if blocks in there, it completely fails to execute. For instance, dropping that whole list of Teleport options in there, causes the entire lot of them to stop functioning completely. Is this a common problem?
User avatar
Romy Welsch
 
Posts: 3329
Joined: Wed Apr 25, 2007 10:36 pm

Post » Fri May 27, 2011 3:04 pm

You'll only need corpses persist if you want a forcegreeting as part of that - otherwise there should be no problem. NPCs are automatically persistent refs (which isn't quite the same thing as a persistent corpse) so PositionCell should always work. (Actually PositionCell, like most Morrowind functions, doesn't always work - but if it fails nothing happens, and trying again usually works.)

Re too-large if-blocks - yes, there's a limit on how much the game can handle, and it does just mess up silently without any error messages if you exceed it. I don't know what the limit is though (and it's probably a limit on the number of compiled commands I would guess). I don't think it always fails in quite the same way either - sometimes it seems to just give up and skip the whole thing, and sometimes it jumps to partway through instead of the endif and executes the last bit regardless of whether the test was true or false.
User avatar
Anna Krzyzanowska
 
Posts: 3330
Joined: Thu Aug 03, 2006 3:08 am

Post » Fri May 27, 2011 4:14 am

Ah ok. I knew about the ForceGreeting problem from my previous work on my companions. I also found out the hard way, that if you use PositionCell on an npc that has never been loaded, you get a CTD, so I just wondered if the 72-hour cleanup would figure into that as well. Good to know it doesn't.
User avatar
Ronald
 
Posts: 3319
Joined: Sun Aug 05, 2007 12:16 am

Post » Fri May 27, 2011 2:42 am

I also found out the hard way, that if you use PositionCell on an npc that has never been loaded, you get a CTD

That can't be right, I've used that myself with no CTDs (moving NPCs from storage cells). I was wondering at first if it might be moving to an active cell that doesn't work, but I realise now I've done that too.

If it's not too much trouble, can you post the script that caused the CTD? I'd like to investigate this a bit if I can.
User avatar
nath
 
Posts: 3463
Joined: Mon Jan 22, 2007 5:34 am

Post » Fri May 27, 2011 4:38 am

Begin Uvirith_DaedraSummon; Summons Ash-Kosh when item is activated.Short doneIf ( MenuMode == 1 )	ReturnEndifIf ( done == -1 )	ReturnEndifIf ( GetJournalIndex HT_UvirithTomb >= 10 )	If ( GetDisabled == 1 )		Enable	EndifElse	If ( GetDisabled == 0 )		Disable	EndIfEndIfIf ( OnActivate == 1 )	If ( done == 1 )		Activate		Return	Else		Set done To 1		"uvi_AshKosh_f"->PositionCell, 4155, 6309, 14625, 0, "Bal Fell, Inner Shrine"		PlaySound3D "conjuration cast"		Set done to 2		Activate		Return	EndIfEndIfIf ( done == 2 )	"uvi_AshKosh_f"->ForceGreeting :Ah HA! this must be the problem then!	Set done to -1	ReturnEndifEnd


I hadn't looked at that script in a while. I forgot that I added a ForceGreeting to it as well, and didn't put two and two together. From what you've said above, it must be the ForceGreeting that's causing the CTD problem if the npc is never loaded, and not the PositionCell then. I solved it long ago by putting the NPC in a holding area in the cell the player had to visit to find the object that summoned it.
User avatar
Rude Gurl
 
Posts: 3425
Joined: Wed Aug 08, 2007 9:17 am

Post » Fri May 27, 2011 12:15 pm

Thanks! :)

Hm, it *could* be the forcegreeting - a fg with a never-loaded NPC didn't crash my game when I tried it, but it didn't work either, so with a fully modded game it might crash (since it's less stable then). I'll see about testing that tonight.
User avatar
Mimi BC
 
Posts: 3282
Joined: Sat Oct 07, 2006 10:30 pm

Post » Fri May 27, 2011 4:23 pm

Arrrgh! I'm still playing hide-and-seek with this npc! It seems that, because I can't put the Teleport block in the CellChanged block because it can't handle that much stuff, she's getting re-positioned as soon as I enter the cell. So whenever I go to where she is, she's already gone to the next area! I know the Teleport is working, because she will eventually return to her quarters in the morning, that is, if I run around in the cells that she may be currently loaded in. See, this is why I need to her teleport when I leave the cell rather than entering it. This is maddening!

Begin Uvi_MeireeScriptShort NoLoreShort FirstGreetingShort FSG ;force greeting dialogue checkShort doOnceShort doOnce2Short RandShort facefix ;fixes disappearing head issue for disabling/enabling vampire npcsShort VampWander ;sets specialized wander modeShort VampWanderCheck ;keeps wander modes stored for dialogueShort Teleport ;teleports to different locations if vampireShort OnPCHitMeShort following ;dialogue check for AiPackageFloat timerIf ( CellChanged == 1 )	If ( uvi_meiree_away == -2 ) ;has been sent back to the Servant's Quarters but not arrived yet.		Disable		Return	Elseif ( uvi_meiree_away == -1 )		Enable		Return	Endif	If ( uvi_meiree_vampire == 0 ) ;normal schedule syncronized with sweeper version		If ( GameHour >= 18 )			Enable		Elseif	( GameHour <= 6 )			Enable		Else			Disable		Endif		Return	Elseif ( uvi_meiree_vampire == 1 ) ;triggers new roaming pattern if she's turned into a vampire by player		Enable ;just in case she was disabled previously		Set facefix to 1		If ( GetJournalIndex HT_Stronghold >= 300 ) ;don't roam around if whole tower is not built yet.			Set Teleport to 1		Endif	Endif		Return	Elseif ( GetPCSleep == 1 )	If ( uvi_meiree_away == -2 ) ;has been sent back to the Servant's Quarters but not arrived yet.		Disable		Return	Elseif ( uvi_meiree_away == -1 )		Enable		Return	Endif	If ( uvi_meiree_vampire == 0 ) ;normal schedule syncronized with sweeper version		If ( GameHour >= 18 )			Enable		Elseif	( GameHour <= 6 )			Enable		Else			Disable		Endif		Return	Elseif ( uvi_meiree_vampire == 1 ) ;triggers new roaming pattern if she's turned into a vampire by player		Enable ;just in case she was disabled previously		Set facefix to 1		If ( GetJournalIndex HT_Stronghold >= 300 ) ;don't roam around if whole tower is not built yet.			Set Teleport to 1		Endif	Endif	ReturnElse	If ( MenuMode == 0 )		If ( servant_meiree_sweeper->GetHealth <= 0 ) ;syncronize deaths with sweeper version			If ( GetDisabled == 0 )				Disable			Endif			Return		Endif		If ( uvi_meiree_away > 95 ) ;has left the tower forever			If ( GetDisabled == 0 )				Disable			Endif			Return		Endif		If ( GetHealth <= 0 ) ;adds sweeper's broom to inventory			If ( doOnce2 == 0 )				AddItem uvi_broom_enchanted 1				Set doOnce2 to 1			Endif		Endif		If ( doOnce == 0 )			If ( GetItemCount emb_memitem_mychilde > 0 ) ;Checks to see if made a vampire by VE. Changes her behavior. Another check is made again in dialogue, just in case.				Set uvi_meiree_vampire to 1				Set doOnce to 1			Endif		Endif		If ( GetPCRank "Telvanni" != -1 ) ;detects if the player is beating Meiree			If ( OnPCHitMe == 1 )				If ( GetHealth < 25 )					If ( FSG == 0 )						Set FSG to 1 ;first chance					Else						Set FSG to 2 ;second chance, only available if vampire child, to take into account accidents if she's following the player around					Endif					StopCombat					Set OnPCHitMe to 0					ForceGreeting				Endif			Endif		Endif		If ( VampWander == 0 ) ;found standing around as usual			Set VampWanderCheck to 0			If ( GetForceSneak == 1 )				ClearForceSneak			Endif			If ( GetSpell Uvi_comp_lev == 1 )				RemoveSpell Uvi_comp_lev			Endif			If ( GetSpell uvi_half_chameleon == 1 )				RemoveSpell uvi_half_chameleon			Endif			Set VampWander to -1		Elseif ( VampWander == 1 ) ;found levitating			Set VampWanderCheck to 1			If ( GetForceSneak == 1 )				ClearForceSneak			Endif			If ( GetSpell Uvi_comp_lev == 0 )				AddSpell Uvi_comp_lev			Endif			If ( GetSpell uvi_half_chameleon == 1 )				RemoveSpell uvi_half_chameleon			Endif			Set VampWander to -1		Elseif ( VampWander == 2 ) ;found sneaking			Set VampWanderCheck to 2			If ( GetForceSneak == 0 )				ForceSneak			Endif			If ( GetSpell Uvi_comp_lev == 1 )				RemoveSpell Uvi_comp_lev			Endif			If ( GetSpell uvi_half_chameleon == 0 )				AddSpell uvi_half_chameleon			Endif			Set VampWander to -1		Endif		If ( uvi_meiree_vampire == 1 )			If ( facefix == 1 )	;fixes disappearing head issue with vampires				Equip uvi_helm_dummy				RemoveItem uvi_helm_dummy 1				Set facefix To 0				Return			EndIf		Endif		If ( GetCurrentAiPackage > 1 )			Set following to 1			Set Teleport to 0			Set VampWander to 0			Return		Else			Set following to 0		Endif		If ( Teleport == 1 ) ;roaming schedule for vampire Meiree if turned into a vampire by player			Set Rand to Random 100			If ( Gamehour >= 21 )				Set uvi_meiree_away to 1				AiWander 1024 5 0 0 10 40 0 10 0 20 0 0				If ( Rand >= 90 )					PositionCell 1104 52 28 270 "Tel Uvirith, Tower Lower"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 80 )					PositionCell 799 -31 1095 0 "Tel Uvirith, Tower Upper"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 70 )					PositionCell 4292 -1065 -1011 0 "Tel Uvirith, Tower Dungeon"					Set VampWander to 2 ;sneaking				Elseif ( Rand >= 60 )					PositionCell 2028 195 -912 0 "Tel Uvirith, Tower Dungeon"					Set VampWander to 2 ;sneaking				Elseif ( Rand >= 50 )					PositionCell 4719 4207 -1679 100 "Tel Uvirith Dungeon, Deep Tunnels"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 30 )					PositionCell 3183 3899 -2259 180 "Tel Uvirith Dungeon, Deep Tunnels"					Set VampWander to 0				Elseif ( Rand >= 0 )					PositionCell 79 181 317 180 "Tel Uvirith, Tower Lower"					Set VampWander to 0				Endif			Elseif ( GameHour <= 5 )				Set uvi_meiree_away to 1				AiWander 1024 5 0 0 10 40 0 10 0 20 0 0				If ( Rand >= 90 )					PositionCell 1104 52 28 270 "Tel Uvirith, Tower Lower"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 80 )					PositionCell 799 -31 1095 0 "Tel Uvirith, Tower Upper"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 70 )				PositionCell 4292 -1065 -1011 0 "Tel Uvirith, Tower Dungeon"					Set VampWander to 2 ;sneaking				Elseif ( Rand >= 60 )					PositionCell 2028 195 -912 0 "Tel Uvirith, Tower Dungeon"					Set VampWander to 2 ;sneaking				Elseif ( Rand >= 50 )					PositionCell 4719 4207 -1679 100 "Tel Uvirith Dungeon, Deep Tunnels"					Set VampWander to 1 ;levitating				Elseif ( Rand >= 30 )					PositionCell 3183 3899 -2259 180 "Tel Uvirith Dungeon, Deep Tunnels"					Set VampWander to 0				Elseif ( Rand >= 0 )					PositionCell 79 181 317 180 "Tel Uvirith, Tower Lower"					Set VampWander to 0				Endif			Else				Set uvi_meiree_away to 0				Set TestVar to 4				AiWander 256 5 0 40 20 10 0 20				PositionCell -724 -102 -256 0 "Tel Uvirith, Servant's Quarter"				Set VampWander to 0			Endif			Set Teleport to 0		Endif	EndifEndifEnd


Looks like I'm going to have to go with the activators in every cell she's supposed to randomly appear in. Sigh...back to the drawing board.
User avatar
Monique Cameron
 
Posts: 3430
Joined: Fri Jun 23, 2006 6:30 am


Return to III - Morrowind