Jump to content

[LE] Removing corpses without breaking respawns or cell resets


Recommended 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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

 

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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.



Auto State WaitingKiller
Event OnDeath(Actor killer)
ObjToActivate01.Activate(self)
ObjToEnable01.Enable()
Self.SetCriticalStage(3)
If ( RunUnequipAll == True )
Self.UnequipAll()
EndIf
If ( CellOwnerRUN ==True )
Utility.Wait(1.0)
Cell01.SetFactionOwner(CellPlayerFaction)
CellOwnerMSG.Show()
EndIf
GoToState("WaitingToRemove")
EndEvent
EndState


State WaitingToRemove
Event OnCellDetach()
count = count + 1
If (count >= CellDetachMax)
Self.SetCriticalStage(4)
EndIf
EndEvent
EndState



I hope it heps.

Edited by maxarturo
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...