Jump to content

Selecting only enemy interiors or enemy NPCs


Recommended Posts

I have a script that will scan all NPCs when I enter an interior. I only want this script to run when I enter a fort or ruin and only run on enemy NPCs. Right now, the only thing I could think of is to limit the script to NPCs in certain factions (Bandit, Necromancer, VampireFaction, and the like). Is there another way to determine if the NPC is an enemy of the player or not? Is there a way to make sure it doesn't run when I enter other places, like homes and businesses?

 

Thanks.

Link to comment
Share on other sites

Most simple, although not much reliable way, would be to use GetCellMusicType command (OBSE) - as most caves, forts and ruins cells are using Dungeon type music.

 

CS Wiki mentions two ways of determining hostility of one actor to another - https://cs.elderscrolls.com/index.php?title=GetShouldAttack.

 

Thanks. That is similar to something else I saw.

 

Here is the latest script. I was working on making the script solve another problem with my game, where some NPCs will start out rotated 90 degrees to my right, and will run and attack in that direction instead of at me. I have solved this by opening the console and doing a disable/enable on the ones that do this. Unfortunately, this causes them to get recreated by the game with re-rolled equipment, spells, and stats.

 

I want to add the ability to scan exteriors too, but am unsure how I would do that and limit it to only run once per cell or area (like it does for interiors).

 

I an trying to see if not letting it run in any cell that has an owner will work, assuming no ruins have an owner.

 

 

 

scn RFScannerQuestScript
float fQuestDelayTime
ref rCurrInterior
ref rInterior1
ref rInterior2
ref rInterior3
short rInteriorNum
ref rDL9Faction
ref rOwner
ref rNPC
ref rNPCBase
ref rItem
ref rItemBase
ref rEnch
short iType
short iNumItems
short iIndex
short iObjType
short iTemp
float fRand
float fTemp
; User set percentages
float fAmazonArmorDegPctMin
float fAmazonArmorDegPctMax
float fAmazonWeapDegPctMin
float fAmazonWeapDegPctMax
float fAmazonWeapChargePctMin
float fAmazonWeapChargePctMax
float fAmazonStaffChargePctMin
float fAmazonStaffChargePctMax
float fMarauderArmorDegPctMin
float fMarauderArmorDegPctMax
float fMarauderWeapDegPctMin
float fMarauderWeapDegPctMax
float fMarauderWeapChargePctMin
float fMarauderWeapChargePctMax
float fMarauderStaffChargePctMin
float fMarauderStaffChargePctMax
float fBanditArmorDegPctMin
float fBanditArmorDegPctMax
float fBanditWeapDegPctMin
float fBanditWeapDegPctMax
float fBanditWeapChargePctMin
float fBanditWeapChargePctMax
float fBanditStaffChargePctMin
float fBanditStaffChargePctMax
float fConjurerArmorDegPctMin
float fConjurerArmorDegPctMax
float fConjurerWeapDegPctMin
float fConjurerWeapDegPctMax
float fConjurerWeapChargePctMin
float fConjurerWeapChargePctMax
float fConjurerStaffChargePctMin
float fConjurerStaffChargePctMax
float fNecroArmorDegPctMin
float fNecroArmorDegPctMax
float fNecroWeapDegPctMin
float fNecroWeapDegPctMax
float fNecroWeapChargePctMin
float fNecroWeapChargePctMax
float fNecroStaffChargePctMin
float fNecroStaffChargePctMax
float fUndeadArmorDegPctMin
float fUndeadArmorDegPctMax
float fUndeadWeapDegPctMin
float fUndeadWeapDegPctMax
float fUndeadWeapChargePctMin
float fUndeadWeapChargePctMax
float fUndeadStaffChargePctMin
float fUndeadStaffChargePctMax
float fVampArmorDegPctMin
float fVampArmorDegPctMax
float fVampWeapDegPctMin
float fVampWeapDegPctMax
float fVampWeapChargePctMin
float fVampWeapChargePctMax
float fVampStaffChargePctMin
float fVampStaffChargePctMax
float fDremArmorDegPctMin
float fDremArmorDegPctMax
float fDremWeapDegPctMin
float fDremWeapDegPctMax
float fDremWeapChargePctMin
float fDremWeapChargePctMax
float fDremStaffChargePctMin
float fDremStaffChargePctMax
float fOtherArmorDegPctMin
float fOtherArmorDegPctMax
float fOtherWeapDegPctMin
float fOtherWeapDegPctMax
float fOtherWeapChargePctMin
float fOtherWeapChargePctMax
float fOtherStaffChargePctMin
float fOtherStaffChargePctMax
float fCreatureArmorDegPctMin
float fCreatureArmorDegPctMax
float fCreatureWeapDegPctMin
float fCreatureWeapDegPctMax
float fCreatureWeapChargePctMin
float fCreatureWeapChargePctMax
float fCreatureStaffChargePctMin
float fCreatureStaffChargePctMax
;=================================
float fArmorDegPctMin
float fArmorDegPctMax
float fWeapDegPctMin
float fWeapDegPctMax
float fWeapChargePctMin
float fWeapChargePctMax
float fStaffChargePctMin
float fStaffChargePctMax
float fCurrentStat
float fBaseStat
array_var arItems
string_var strHexID
string_var strHexIDBase
short bCantRun
short bEnableNeeded
Begin GameMode
if GetGameLoaded
  set fQuestDelayTime to 0.5
  if FileExists "Data\ini\RicksDegradeStuff.ini"
   PrintC"RicksDegradeStuff - Reading settings from ini file"
   RunBatchScript "Data\ini\RicksDegradeStuff.ini"
   set bCantRun to 0
   if IsModLoaded "DLCMehrunesRazor.esp"
    set rDL9Faction to GetFormFromMod "DLCMehrunesRazor.esp" "14E9"
   else
    set rDL9Faction to 0
   endif
  else
   set bCantRun to 1
   MessageBox "Ricks Degrade Stuff - Can't read ini file."
  endif
  return
endif
if bCantRun
  return
endif
if bEnableNeeded
  set bEnableNeeded to 0
  set fQuestDelayTime to 0.5
  set rNPC to GetFirstRef 69
  while (rNPC)
   ;PrintC"==================================== Found Actor: %n ==================" rNPC
   set rNPCBase to rNPC.GetBaseObject
   if rNPC.GetObjectType == 35 && rNPC.GetItemCount RFDisabledToken > 0
    rNPC.RemoveItem RFDisabledToken 1
    rNPC.Enable
   endif
   set rNPC to GetNextRef
  loop
  return
endif
if player.IsInInterior

  set rOwner to player.GetParentCellOwner
  if rOwner
   return
  endif
  set rCurrInterior to player.GetParentCell
  if rCurrInterior == rInterior1 || rCurrInterior == rInterior2 || rCurrInterior == rInterior3
   return
  endif  
  set rInteriorNum to rInteriorNum + 1
  if rInteriorNum > 3
   set rInteriorNum to 1
  endif
  if rInteriorNum == 1
   set rInterior1 to rCurrInterior
  elseif rInteriorNum == 2
   set rInterior2 to rCurrInterior
  else
   set rInterior3 to rCurrInterior
  endif
  set bEnableNeeded to 0
  set rNPC to GetFirstRef 69
  while (rNPC)
   ;PrintC"==================================== Found Actor: %n ==================" rNPC
   set rNPCBase to rNPC.GetBaseObject
   if rNPC.GetObjectType == 35 ||  (rNPC.GetObjectType == 36 && rNPC.CreatureUsesWeaponAndShield)  ; NPC or armed creature
    if rNPC.GetItemCount RFScannedToken == 0
     rNPC.AddItem RFScannedToken 1
     set fArmorDegPctMax to 0.0
     if rNPC.GetInFaction AmazonFaction
      ;PrintC"NPC %n Being processed..." rNPCBase
      set fArmorDegPctMax to fAmazonArmorDegPctMax
      set fArmorDegPctMin to fAmazonArmorDegPctMin
      set fWeapDegPctMax to fAmazonWeapDegPctMax
      set fWeapDegPctMin to fAmazonWeapDegPctMin
      set fWeapChargePctMax to fAmazonWeapChargePctMax
      set fWeapChargePctMin to fAmazonWeapChargePctMin
      set fStaffChargePctMax to fAmazonStaffChargePctMax
      set fStaffChargePctMin to fAmazonStaffChargePctMin
     elseif rNPC.GetInFaction MarauderFaction || (rDL9Faction != 0 && rNPC.GetInFaction rDL9Faction)
      set fArmorDegPctMax to fMarauderArmorDegPctMax
      set fArmorDegPctMin to fMarauderArmorDegPctMin
      set fWeapDegPctMax to fMarauderWeapDegPctMax
      set fWeapDegPctMin to fMarauderWeapDegPctMin
      set fWeapChargePctMax to fMarauderWeapChargePctMax
      set fWeapChargePctMin to fMarauderWeapChargePctMin
      set fStaffChargePctMax to fMarauderStaffChargePctMax
      set fStaffChargePctMin to fMarauderStaffChargePctMin
     elseif rNPC.GetInFaction BanditFaction || rNPC.GetInFaction VeyondCaveBandits
      set fArmorDegPctMax to fBanditArmorDegPctMax
      set fArmorDegPctMin to fBanditArmorDegPctMin
      set fWeapDegPctMax to fBanditWeapDegPctMax
      set fWeapDegPctMin to fBanditWeapDegPctMin
      set fWeapChargePctMax to fBanditWeapChargePctMax
      set fWeapChargePctMin to fBanditWeapChargePctMin
      set fStaffChargePctMax to fBanditStaffChargePctMax
      set fStaffChargePctMin to fBanditStaffChargePctMin
     elseif rNPC.GetInFaction ConjurerFaction
      set fArmorDegPctMax to fConjurerArmorDegPctMax
      set fArmorDegPctMin to fConjurerArmorDegPctMin
      set fWeapDegPctMax to fConjurerWeapDegPctMax
      set fWeapDegPctMin to fConjurerWeapDegPctMin
      set fWeapChargePctMax to fConjurerWeapChargePctMax
      set fWeapChargePctMin to fConjurerWeapChargePctMin
      set fStaffChargePctMax to fConjurerStaffChargePctMax
      set fStaffChargePctMin to fConjurerStaffChargePctMin
     elseif rNPC.GetInFaction NecromancerDungeon || rNPC.GetInFaction NecromancerFaction
      set fArmorDegPctMax to fNecroArmorDegPctMax
      set fArmorDegPctMin to fNecroArmorDegPctMin
      set fWeapDegPctMax to fNecroWeapDegPctMax
      set fWeapDegPctMin to fNecroWeapDegPctMin
      set fWeapChargePctMax to fNecroWeapChargePctMax
      set fWeapChargePctMin to fNecroWeapChargePctMin
      set fStaffChargePctMax to fNecroStaffChargePctMax
      set fStaffChargePctMin to fNecroStaffChargePctMin
     elseif rNPC.GetInFaction UndeadFaction
      set fArmorDegPctMax to fUndeadArmorDegPctMax
      set fArmorDegPctMin to fUndeadArmorDegPctMin
      set fWeapDegPctMax to fUndeadWeapDegPctMax
      set fWeapDegPctMin to fUndeadWeapDegPctMin
      set fWeapChargePctMax to fUndeadWeapChargePctMax
      set fWeapChargePctMin to fUndeadWeapChargePctMin
      set fStaffChargePctMax to fUndeadStaffChargePctMax
      set fStaffChargePctMin to fUndeadStaffChargePctMin
  
     elseif rNPC.GetInFaction VampireFaction
      set fArmorDegPctMax to fVampArmorDegPctMax
      set fArmorDegPctMin to fVampArmorDegPctMin
      set fWeapDegPctMax to fVampWeapDegPctMax
      set fWeapDegPctMin to fVampWeapDegPctMin
      set fWeapChargePctMax to fVampWeapChargePctMax
      set fWeapChargePctMin to fVampWeapChargePctMin
      set fStaffChargePctMax to fVampStaffChargePctMax
      set fStaffChargePctMin to fVampStaffChargePctMin
     elseif rNPC.GetInFaction DremoraFaction
      set fArmorDegPctMax to fDremArmorDegPctMax
      set fArmorDegPctMin to fDremArmorDegPctMin
      set fWeapDegPctMax to fDremWeapDegPctMax
      set fWeapDegPctMin to fDremWeapDegPctMin
      set fWeapChargePctMax to fDremWeapChargePctMax
      set fWeapChargePctMin to fDremWeapChargePctMin
      set fStaffChargePctMax to fDremStaffChargePctMax
      set fStaffChargePctMin to fDremStaffChargePctMin
     elseif rNPC.isActorEvil
      if rNPC.GetDisposition player < 20.0 ; NPC is hostile to the player
       set fArmorDegPctMax to fOtherArmorDegPctMax
       set fArmorDegPctMin to fOtherArmorDegPctMin
       set fWeapDegPctMax to fOtherWeapDegPctMax
       set fWeapDegPctMin to fOtherWeapDegPctMin
       set fWeapChargePctMax to fOtherWeapChargePctMax
       set fWeapChargePctMin to fOtherWeapChargePctMin
       set fStaffChargePctMax to fOtherStaffChargePctMax
       set fStaffChargePctMin to fOtherStaffChargePctMin
      endif
     elseif rNPC.IsCreature
       set fArmorDegPctMax to fCreatureArmorDegPctMax
       set fArmorDegPctMin to fCreatureArmorDegPctMin
       set fWeapDegPctMax to fCreatureWeapDegPctMax
       set fWeapDegPctMin to fCreatureWeapDegPctMin
       set fWeapChargePctMax to fCreatureWeapChargePctMax
       set fWeapChargePctMin to fCreatureStaffChargePctMin
       set fStaffChargePctMax to fCreatureStaffChargePctMax
       set fStaffChargePctMin to fCreatureStaffChargePctMin     
     endif
;=======================================================================================    
;    Weapon Type:
;     0:    Blade1H
;     1:    Blade2H
;     2:    Blunt1H
;     3:    Blunt2H
;     4:    Staff
;     5:    Bow
;=================================================================================== (min + GetRandomPercent * (max-min+1)) / 100
     if fArmorDegPctMax > 0
      if rNPC.GetDead == 0 && rNPC.GetDisabled == 0
       ;rNPC.Reset3DState
       rNPC.EVP
      endif
      ;if rNPC.GetDisabled == 0
       ;rNPC.Disable
       ;rNPC.AddItem RFDisabledToken 1
       ;set bEnableNeeded to 1
       ;set fQuestDelayTime to 0.02
      ;endif
      ForEach rItem <- rNPC
       set rItemBase to rItem.GetBaseObject
       set iObjType to rItem.GetObjectType
       ;sv_Destruct strHexID strHexIDBase
       set fBaseStat to GetObjectHealth rItemBase
      
       if iObjType == 20   ; Armor
        let fRand := Rand fArmorDegPctMin, fArmorDegPctMax
        set fRand to fRand / 100.0
        set fRand to fBaseStat * fRand
        rItem.SetCurrentHealth fRand
        ;PrintC"Setting Armor %n to Health %.2f (of max %.2f" rItem, fRand, fBaseStat
       elseif iObjType == 33 ; Weapon
        set iType to rItem.GetWeaponType
        if iType != 4
         set fBaseStat to GetObjectHealth rItemBase
         let fRand := Rand fWeapDegPctMin, fWeapDegPctMax
         set fRand to fRand / 100.0
         set fRand to fBaseStat * fRand
         rItem.SetCurrentHealth fRand
         ;PrintC"Setting Weapon %n to Health %.2f (of max %.2f" rItem, fRand, fBaseStat
         let rEnch := GetEnchantment rItemBase
         if rEnch
          set fBaseStat to GetObjectCharge rItemBase
          let fRand := Rand fWeapChargePctMin, fWeapChargePctMax
          set fRand to fRand / 100.0
          set fRand to fBaseStat * fRand
          rItem.SetCurrentCharge fRand
          ;PrintC"Setting Weapon charge for %n to charge %.2f (of max %.2f" rItem, fRand, fBaseStat
         endif
        else
         let fRand := Rand fStaffChargePctMin, fStaffChargePctMax
         set fRand to fRand / 100.0
         set fRand to fBaseStat * fRand
         rItem.SetCurrentCharge fRand
         ;PrintC"Setting Staff %n to Charge %.2f (of max %.2f" rItem, fRand, fBaseStat
        endif       
       endif
      loop
     endif
    endif
   endif
  
   set rNPC to GetNextRef
  loop ;
endif
end

 

 

Edited by GamerRick
Link to comment
Share on other sites

I don't know. All I know is that doing a disable/enable on that NPC fixes it, but it also rerolls them again from scratch (different equipment and spells for starters). I also have no idea how to ID an NPC in a script that has this bug. I will try to rotate them in the console and see what happems.

 

This is a problem in my script, because I would change the NPC's weapons and armor and then disable them, and then the next time the script is called it enables them. I would need to do the weapon and armor changes after enabling them. But for now, I am trying to see if something as simple as doing an EVP on them will work. So far it has. The Reset3DState command caused a CTD eventually.

Edited by GamerRick
Link to comment
Share on other sites

OK, for now I made a script in form of function which takes an NPC reference as a parameter and will rotate the NPC to face you. I can't say if it will be enough, but here it is:

 

 

 

scn RomRFaceMeFnSetAngle
ref actor
float actor_x
float actor_y
float player_x
float player_y
float a
float b
float c
float temp
float angle
short quadrant

begin function { actor }
	set angle to -1
	set quadrant to 0
	set actor_x to actor.GetPos X
	set actor_y to actor.GetPos Y
	set player_x to player.GetPos X
	set player_y to player.GetPos Y
	set a to player_x - actor_x
	set b to player_y - actor_y
	;print $a
	;print $b
	if a != 0 || b != 0
		; most simple case
		if a == 0 
			if b > 0
				set angle to 0
			endif
			if b < 0
				set angle to 180
			endif
		endif
		if b == 0
			if a > 0
				set angle to 90
			endif
			if a < 0
				set angle to 270
			endif
		endif
		; all other cases
		if angle == -1
			; determining quadrant
			if a > 0 && b > 0
				set quadrant to 1 ; 0 - 89
			endif
			if a > 0 && b < 0
				set quadrant to 2 ; 90 - 179
			endif
			if a < 0 && b > 0
				set quadrant to 4 ; 270 - 359
			endif
			if a < 0 && b < 0
				set quadrant to 3 ;  180 - 269
			endif
			;print $quadrant
			; "distance" c
			set c to a 
			if c < 0
				set c to 0 - c
			endif
			set c to c * c
			set temp to b 
			if temp < 0
				set temp to 0 - temp
			endif
			set temp to temp * temp
			set c to c + temp
			let c := sqrt c
			;print $c
			; angle
			set angle to a/c
			if angle < 0
				set angle to 0 - angle
			endif
			let angle := ASin angle 
		endif
		if angle != -1
			if quadrant == 0
				actor.SetAngle Z angle
			else
				if quadrant == 1
					actor.SetAngle Z angle
				endif
				if quadrant == 2
					set angle to 180 - angle
					actor.SetAngle Z angle
				endif
				if quadrant == 3
					set angle to 180 + angle
					actor.SetAngle Z angle
				endif
				if quadrant == 4
					set angle to 360 - angle
					actor.SetAngle Z angle
				endif
			endif
			;print $angle
		endif
	endif
end

 

 

 

Link to comment
Share on other sites

Thanks! I am seeing the problem still occur, which means the EVP doesn't do squat. But I just found that doing a 'setangle y' on an NPC in the console has no effect at all. With other objects, you would have to do the disable/enable thing to get any setpos or setangle to work. What I found with NPCs is that this doesn't work at all on them anyway. Even it you disable them first and then do a setpos or setangle on them, when they're enabled, the game re-rolls them and then places them where it wants to, probably based a bit on the path-grid. So, years ago when I tried to replace one NPC with another, I could never get the new NPC to appear exactly where the first one was.

 

So, since the ONLY way to fix this is to disable/enable them anyway, I decided to just change my script to perform the weapon and armor degrades after then are enabled. It all happens when I first enter the cell for the first time, so I only notice this when I enter an interior that has NPC(s) that I can see right away.

 

I see no way to determine what NPCs are at the 90 degree CCW angle to me. Even doing a getangle shows nothing that would indicate this NPC needs to be actioned. However, it never happens to creatures. So, I can just limit it to NPCs only.

 

I would love to figure out why this happens. Is it something you've heard about before? It it just me?

Edited by GamerRick
Link to comment
Share on other sites

If you look closely to my script, you see that I'm setting angle on Z axis, not Y. I tested this function as a part of experimental Face Me spell and result was good - the affected NPC was always facing the player's direction as I moved PC around. You can easily modify the script to return the angle only and compare it to actual NPC's.

 

I haven't much ideas why the NPC are rotated that way you're speaking, I can only speculate it's some init thing as you enter particular cell. It sometimes happens to me to, often if there are NPCs or creatures of opposite faction - seems the PC is somewhat last in init order and sometimes I witness already running battle, for example between marauders and bandits. Of course I can't deny possibility of some mod's influence. But I was never concerned about it much, because I must often kill all hostile actors anyway.

Edited by RomanR
Link to comment
Share on other sites

  • Recently Browsing   0 members

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