Jump to content

Photo

Removing corpses without breaking respawns or cell resets

papyrus

  • Please log in to reply
8 replies to this topic

#1
ZauberParacelsus

ZauberParacelsus

    Fan

  • Members
  • PipPipPip
  • 273 posts

I created a mod called Corpse to Coinage, which gives you a spell that turns corpses into a small amount of money.  One major issue I've had with this mod, however, is that any corpses removed by it are removed permanently, meaning that when the cell resets, the enemies will not be respawned.  This can also break some radiant quests, if the quest target is an enemy that had their corpse deleted.

 

The following code is what is used for removing a corpse:

akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)

Are there any better methods for removing corpses?  I've tried sending them to the corpse cleanup cell, which also seems to remove them permanently.



#2
maxarturo

maxarturo

    Faithful poster

  • Members
  • PipPipPipPip
  • 1,734 posts
Post the whole code.
 
This line
akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)
requires to work along side with
akTarget.SetCriticalStage(3)
 
Like this:
akTarget.SetCriticalStage(3)
Utility.Wait(0.1)
akTarget.SetCriticalStage(4)


#3
ZauberParacelsus

ZauberParacelsus

    Fan

  • Members
  • PipPipPip
  • 273 posts

 

Post the whole code.
 
This line
akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)
requires to work along side with
akTarget.SetCriticalStage(3)
 
Like this:
akTarget.SetCriticalStage(3)
Utility.Wait(0.1)
akTarget.SetCriticalStage(4)

 

 

Here is my code:

Scriptname CorpseToCoinScript extends activemagiceffect  

Activator Property GoldBag  Auto
MiscObject Property GoldCoin  Auto
Keyword Property akDragon  Auto
GlobalVariable Property HealthMult  Auto
GlobalVariable Property MagickaMult  Auto
GlobalVariable Property StaminaMult  Auto
GlobalVariable Property IncludeItems  Auto
Explosion Property HitExplosion  Auto
EffectShader Property HitShader  Auto


float Function Max(float x, float y)
	if(x >= y)
		return x
	endIf
	return y
endFunction

float Function Min(float x, float y)
	if(x <= y)
		return x
	endIf
	return y
endFunction


int Function CountGold(Actor akTarget, float GoldMult)
	int CL = Max(1, akTarget.GetLevel()) as int
	int CH = Max(1, akTarget.GetActorValueMax("Health") * HealthMult.GetValue()) as int
	CH = Max(CH, akTarget.GetActorValueMax("Magicka") * MagickaMult.GetValue()) as int
	CH = Max(CH, akTarget.GetActorValueMax("Stamina") * StaminaMult.GetValue()) as int
	if(akTarget.GetRace().HasKeyword(akDragon))
		CH *= 5
	endIf
	
	return Math.Ceiling((CL + CH) * GoldMult) as int
endFunction


int Function CalcInventoryGold(Actor akTarget, float GoldMult)
	if(IncludeItems.GetValue() == 0)
		return akTarget.GetItemCount(GoldCoin)
	endIf
	int len = akTarget.GetNumItems()
	if(len == 0)
		return 0
	endIf
	int i = 0
	int goldTotal = 0
	While i < len
		Form item = akTarget.GetNthForm(i)
		if(item.IsPlayable() == true)
			int goldSub = akTarget.GetItemCount(item) * Math.Ceiling(item.GetGoldValue()* GoldMult)
			if(goldSub >= 1)
				goldTotal += goldSub
			endIf
		endIf
		i += 1
	EndWhile
	return goldTotal
endFunction


Function SpawnPurse(Actor akTarget, int GoldTotal)
	if(GoldTotal == 1)
		akTarget.PlaceAtMe(GoldCoin)
	else
		ObjectReference Purse = akTarget.PlaceAtMe(GoldBag)
		Purse.SetDisplayName("Corpse Coinage (" + (GoldTotal as string) + ")")
		float PurseScale = Max(0.5, Min(5.0, Math.Log(GoldTotal/20) / 2.0))
		Purse.SetScale(PurseScale)
		float posX = Purse.GetPositionX()
		float posY = Purse.GetPositionY()
		float posZ = Purse.GetPositionZ() + (PurseScale / 2) - 0.25
		Purse.SetPosition(posX, posY, posZ)
		HitShader.play(Purse, 3)
	endIf
EndFunction


Event OnEffectStart(Actor akTarget, Actor akCaster)
	if(akTarget.isDead() == 0)
		debug.notification("Corpse to Coinage only works on dead bodies")
		return
	endIf
	if(akTarget.IsActivationBlocked())
		return
	endIf
	akTarget.BlockActivation()
	float GoldMult = Min(0.1 + (akCaster.GetActorValue("Alteration") * 0.009), 1.0)

	int GoldTotal = CountGold(akTarget, goldMult)
	int CalcGold = CalcInventoryGold(akTarget, GoldMult)
	if(CalcGold == -1)
		return
	endIf
	
	GoldTotal += CalcGold	
	akTarget.placeAtMe(HitExplosion)
	SpawnPurse(akTarget, GoldTotal)
	akTarget.disable()
	utility.wait(1)
	akTarget.BlockActivation(False)
	akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)
EndEvent


#4
maxarturo

maxarturo

    Faithful poster

  • Members
  • PipPipPipPip
  • 1,734 posts
Your issue :
akTarget.disable()
 
Try without "Disable()":
Event OnEffectStart()
         akTarget.SetCriticalStage(3)
Endevent
 
Event OnEffectFinish()
         akTarget.SetCriticalStage(4)
Endevent

 

EDIT: stupid mistake


Edited by maxarturo, 30 June 2020 - 05:02 PM.


#5
ZauberParacelsus

ZauberParacelsus

    Fan

  • Members
  • PipPipPip
  • 273 posts

I've tested without running disable() before and it didn't help.

 

Anyways, I've changed it to work as above, and while the corpse *is* being removed, when I leave and then come back the corpse has returned.  I don't think OnEffectFinish() is being run.



#6
maxarturo

maxarturo

    Faithful poster

  • Members
  • PipPipPipPip
  • 1,734 posts
If you call "Disable" before the "SetCriticalStage" the last it won't fire.
Plus the actor will remain 'Disable" and will not respawn.
 
"when I leave and then come back the corpse has returned"
I don't know why you are facing this, but calling both "SetCriticalStage" functions is something that i do a lot in the last mod i recently released because is essential for a lot of cells to remove the dead actors and it always fire and works just fine.
Spoiler
 
I hope it heps.

Edited by maxarturo, 30 June 2020 - 05:25 PM.


#7
ZauberParacelsus

ZauberParacelsus

    Fan

  • Members
  • PipPipPip
  • 273 posts

I've got it fully working now!  I just took that stuff in OnEffectEnd and put them onto the end of OnEffectStart, like so:

akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateStart)
akTarget.BlockActivation(False)
akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)

Gonna do some more testing though, to make sure no other issues come up.  Glad to see respawning finally working again, I was worried I'd have to do something really convoluted in order to fix it.



#8
maxarturo

maxarturo

    Faithful poster

  • Members
  • PipPipPipPip
  • 1,734 posts
Just a heads up.
 
I have notice that this:
akTarget.SetCriticalStage(3)
akTarget.SetCriticalStage(4)
 
Is faster and more reliable than this:
akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateStart)
akTarget.SetCriticalStage(akTarget.CritStage_DisintegrateEnd)
 
Have a happy modding.


#9
ZauberParacelsus

ZauberParacelsus

    Fan

  • Members
  • PipPipPip
  • 273 posts

Aye, thanks again.







Also tagged with one or more of these keywords: papyrus

Page loaded in: 1.057 seconds