Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Scriptname Scavver extends Actor
- { It just works. }
- ; SCAVVER MOD BY @THORALDGM | [email protected] | SCRIPT UPDATED 20160620
- ; -----------------------------------------------------------------------------
- ; PROPERTIES
- ; -----------------------------------------------------------------------------
- ObjectReference Property pScavver Auto Const Mandatory ; Scavver ObjRef
- Actor Property pScavverActor Auto Const Mandatory ; Scavver ActorRef
- GlobalVariable Property pgvScavverStatusSniffer Auto Mandatory ; Toggle tracking on/off
- GlobalVariable Property pgvScavverWeaponValue Auto Mandatory ; Best weapon found stat
- Form Property pScavverPreferredWeapon Auto ; Best weapon found form
- Ammo Property pScavverWeaponAmmo Auto ; Ammo for current weapon
- GlobalVariable Property pgvScavverArmorValue Auto Mandatory ; Best armor found stat
- FormList Property pScavverArmorAllowed Auto Const Mandatory ; Outfits Scavver can wear (45)
- Armor Property pRoadGoggles Auto Const Mandatory ; Radstorm goggles
- Armor Property pSurgicalMask Auto Const Mandatory ; Radstorm mask
- Weather Property pRadstorm Auto Const Mandatory ; Radstorm weather
- Keyword Property pObjectTypeAmmo Auto Const Mandatory ; Is looted item ammo?
- Keyword Property pObjectTypeArmor Auto Const Mandatory ; Is looted item armor?
- Keyword Property pObjectTypeWeapon Auto Const Mandatory ; Is looted item weapon?
- GlobalVariable Property pgvScavverStartedRemoveAll Auto Mandatory ; Is RemoveAllItems loop active?
- GlobalVariable Property pgvScavverRemoveAllRestartPkg Auto Mandatory
- GlobalVariable Property pgvScavverScruffStage Auto Mandatory ; Current facial hair
- FormList Property pScavverScruffList Auto Const Mandatory ; List of facial hair growth parts
- ObjectReference Property pScavverVendorContainer Auto Const Mandatory ; Scavver vendor container
- ObjectReference Property pScavverMarker Auto Const Mandatory ; Alert system for stuck NPCs
- ObjectReference Property pScavverTriggerVolume Auto Const Mandatory ; Trigger volume is stuck path failsafe
- GlobalVariable Property pgvScavverWasStuck Auto Mandatory ; Is Scavver on a difficult path?
- GlobalVariable Property pgvScavverIsIndoors Auto Mandatory ; Is Scavver indoors? (vault, etc)
- ; ----------------------------------------------------------------------------
- ; EVENT: ON INIT
- ; -----------------------------------------------------------------------------
- Event OnInit()
- AddInventoryEventFilter(None) ; Required filter for OnItemAdded
- RegisterForRadiationDamageEvent(Game.GetPlayer()) ; Enables OnRadiationDamage event
- pScavverMarker.MoveTo(pScavver) ; Place marker at Scavver
- pScavverTriggerVolume.MoveTo(pScavver) ; Place trigger volume at Scavver
- CancelTimer(3) ; This is the 3rd event in my timer
- Utility.Wait(1) ; Wait a second
- StartTimer(10, 3) ; Fire timer code in 10 seconds
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON ITEM ADDED (CHOOSE BEST EQUIPS FOR SELF, LOOT CONTAINER, BROADCAST)
- ;
- ; SCAVVER HAS SWEEP AI PACKAGE IN CREATION KIT WITH FIND & ACQUIRE PROCEDURES FOR:
- ; WEAPONS, AMMO, ARMOR, FOOD, & RADAWAY.
- ;
- ; IMPORTANT:
- ;
- ; REMOVEALLITEMS PIGGYBACKS OFF OF THE ACQUIRE PROCEDURE TO LOOT REST OF CONTAINER.
- ; THE STATE CHANGE IS THERE TO AVOID OVERLAPPING CALLS TO REMOVEALLITEMS FUNCTION.
- ; -----------------------------------------------------------------------------
- Event OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)
- string StuffAndThangs = "stuff and thangs"
- string FromWhere = "somewhere"
- int NumItemsLeft
- float WeaponValue
- float WeaponGlobal
- float ArmorValue
- float ArmorGlobal
- bool IsEquipSilent = true
- ; UNLOCK LOOTED CONTAINER SO IT DOESN'T DISPLAY (UNLOCK - EMPTY) PROMPT
- If akSourceContainer
- If akSourceContainer.IsLocked()
- akSourceContainer.Lock(false)
- EndIf
- EndIf
- ; DISPLAY NOTIFICATION IF TRACKING
- If pgvScavverStatusSniffer.GetValue() == 1
- ; Assign item name for notification
- If akBaseItem.HasKeyword(pObjectTypeAmmo)
- StuffAndThangs = "ammo"
- ElseIf akBaseItem.HasKeyword(pObjectTypeArmor)
- StuffAndThangs = "armor"
- ElseIf pScavverArmorAllowed.HasForm(akBaseItem)
- StuffAndThangs = "outfit"
- ElseIf akBaseItem.HasKeyword(pObjectTypeWeapon)
- StuffAndThangs = "weapon"
- Else
- StuffAndThangs = "an item"
- EndIf
- ; Assign container name for notification
- If !akSourceContainer
- FromWhere = "the world"
- ElseIf akSourceContainer == Game.GetPlayer()
- FromWhere = "the player"
- ; ElseIf (akSourceContainer as Actor).IsDead()
- ; FromWhere = "a corpse"
- Else
- FromWhere = "a container"
- EndIf
- Debug.Notification("Scavver took " + StuffAndThangs + " from " + FromWhere + ".")
- EndIf
- ; PROCESS ADDED WEAPON
- If akBaseItem.HasKeyword(pObjectTypeWeapon)
- WeaponValue = akBaseItem.GetGoldValue() ; Get value of added weapon
- WeaponGlobal = pgvScavverWeaponValue.GetValue() ; Get current value of weapon global
- Utility.Wait(1)
- ; Debug.MessageBox("WeaponV: " + WeaponValue + ". WeaponG: " + WeaponGlobal)
- If pgvScavverStatusSniffer.GetValue() == 1
- IsEquipSilent = false
- Else
- IsEquipSilent = true
- EndIf
- If(WeaponValue >= WeaponGlobal)
- ; Debug.MessageBox("WEAPON VALUE >= WEAPON GLOBAL")
- pScavverActor.EquipItem(akBaseItem, true, IsEquipSilent) ; Scavver uses best weapon found
- pScavverPreferredWeapon = akBaseItem ; Save weapon form so can restore as needed (fix combat AI chaos)
- pgvScavverWeaponValue.SetValue(WeaponValue) ; Update global with new higher value!!!
- ; Debug.MessageBox("NEW WEAPON GLOBAL IS: " + pgvScavverWeaponValue.GetValue())
- Utility.Wait(1)
- pScavverActor.DrawWeapon() ; Quick visual confirmation of weapon change
- EndIf
- EndIf
- ; PROCESS ADDED ARMOR
- If pScavverArmorAllowed.HasForm(akBaseItem) ; If armor is on the list
- ArmorValue = akBaseItem.GetGoldValue() ; Get value of added armor
- ArmorGlobal = pgvScavverArmorValue.GetValue() ; Get current value of armor global
- Utility.Wait(1)
- ; Debug.MessageBox("ArmorV: " + ArmorValue + ". ArmorG: " + ArmorGlobal)
- If pgvScavverStatusSniffer.GetValue() == 1
- IsEquipSilent = false
- Else
- IsEquipSilent = true
- EndIf
- If ArmorValue >= ArmorGlobal
- ; Debug.MessageBox("ARMOR VALUE >= ARMOR GLOBAL")
- pScavverActor.EquipItem(akBaseItem, true, IsEquipSilent) ; Scavver uses best armor found
- pgvScavverArmorValue.SetValue(ArmorValue) ; Update global with new higher value!!!
- ; Debug.MessageBox("NEW ARMOR GLOBAL IS: " + pgvScavverArmorValue.GetValue())
- EndIf
- EndIf
- ; PIGGYBACK CK PROCEDURE TREE TO TAKE REST OF ITEMS IN CONTAINER (INCREASES LOOT AMOUNT & VARIETY)
- If akSourceContainer
- NumItemsLeft = akSourceContainer.GetItemCount()
- If (akSourceContainer != Game.GetPlayer()) && (akSourceContainer != pScavverVendorContainer) && (NumItemsLeft > 0)
- If pgvScavverStartedRemoveAll.GetValue() == 0 ; If started flag not set
- pgvScavverStartedRemoveAll.SetValue(1) ; Set started flag
- akSourceContainer.RemoveAllItems(pScavver, false) ; Loot container
- CancelTimer(1)
- Utility.Wait(1)
- StartTimer(5, 1) ; Reset started flag to 0 in 5 seconds
- pgvScavverRemoveAllRestartPkg.SetValue(1) ; Inform sweep package that my code is restarting package
- pScavverActor.EvaluatePackage() ; Stop Scavver from returning to looted containers
- EndIf
- EndIf
- EndIf
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON COMBAT STATE CHANGED
- ; -----------------------------------------------------------------------------
- Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
- If pgvScavverStatusSniffer.GetValue() == 1
- If aeCombatState == 0
- Debug.Notification("Scavver is no longer fighting.")
- ElseIf aeCombatState == 1
- Debug.Notification("Scavver is fighting.")
- ElseIf aeCombatState == 2
- Debug.Notification("Scavver is hunting his attacker.")
- EndIf
- EndIf
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON KILL (LOOT CORPSE)
- ; -----------------------------------------------------------------------------
- Event OnKill(Actor akVictim)
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("Scavver killed his attacker.")
- EndIf
- pgvScavverStartedRemoveAll.SetValue(0) ; Reset started flag now just to be sure
- akVictim.RemoveAllItems(pScavver, false) ; Loot corpse
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON LOCATION CHANGE
- ; -----------------------------------------------------------------------------
- Event OnLocationChange(Location akOldLoc, Location akNewLoc)
- int MaxAmmo = 50
- int AmmoCount
- float NowIndex = pgvScavverScruffStage.GetValue()
- float NextIndex = NowIndex + 1
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("Scavver changed location.")
- Utility.Wait(1)
- EndIf
- If pScavver.IsInInterior()
- pgvScavverIsIndoors.SetValue(1)
- pgvScavverWasStuck.SetValue(1)
- GetScavverUnstuck()
- EndIf
- If NowIndex == 6 ; If current facial hair is last in the list (of 7 entries) ...
- NextIndex = 0 ; Set next facial hair to the first entry
- EndIf
- pScavverActor.ChangeHeadPart((pScavverScruffList.GetAt((NowIndex as Int)) as HeadPart), true, true) ; Remove current facial hair
- pScavverActor.ChangeHeadPart((pScavverScruffList.GetAt((NextIndex as Int))) as HeadPart) ; Add the next facial hair
- pgvScavverScruffStage.SetValue(NextIndex) ; Update global to new facial hair
- ; Debug.MessageBox("BEARD IS NOW: " + NextIndex)
- If !(pScavverActor.IsEquipped(pScavverPreferredWeapon))
- pScavverActor.EquipItem(pScavverPreferredWeapon, true, true) ; Fix for combat AI chaos
- EndIf
- If (pScavverPreferredWeapon as Weapon).GetAmmo()
- pScavverWeaponAmmo = (pScavverPreferredWeapon as Weapon).GetAmmo()
- AmmoCount = pScavver.GetItemCount(pScavverWeaponAmmo)
- ; Debug.Notification("Scavver ammo count start: " + AmmoCount)
- While AmmoCount < MaxAmmo
- pScavver.AddItem(pScavverWeaponAmmo) ; Give Scavver ammo for wielded weapon
- AmmoCount += 1
- EndWhile
- ; Utility.Wait(1)
- ; Debug.Notification("Scavver ammo count end: " + AmmoCount)
- ; Utility.Wait(1)
- EndIf
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON RADIATION DAMAGE (EQUIP GOGGLES & MASK)
- ; -----------------------------------------------------------------------------
- Event OnRadiationDamage(ObjectReference akTarget, bool abIngested)
- If (!abIngested && !(pScavverActor.IsEquipped(pSurgicalMask)))
- String RadSource = "radiation"
- pScavverActor.EquipItem(pRoadGoggles, true, true)
- pScavverActor.EquipItem(pSurgicalMask, true, true)
- CancelTimer(2)
- Utility.Wait(1)
- If Weather.GetCurrentWeather() == pRadstorm
- StartTimer(240, 2) ; Rad storm is ~4 real minutes
- RadSource = "radstorm"
- ; Debug.MessageBox("RAD STORM TIMER STARTED")
- Else
- StartTimer(30, 2) ; Check if roaches/barrels gone in 30 seconds
- RadSource = "rad objects"
- ; Debug.MessageBox("RAD EXPOSURE TIMER STARTED")
- EndIf
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("Scavver put on " + RadSource + " gear.")
- EndIf
- Else
- RegisterForRadiationDamageEvent(Game.GetPlayer()) ; Catch the next radiation event
- EndIf
- EndEvent
- ; ------------------------------------------------------------------------------------------
- ; EVENT: ON TIMER (1 = RESET STARTED FLAG, 2 = REMOVE GOGGLES & MASK, 3 = MOVE NPC IF STUCK)
- ; ------------------------------------------------------------------------------------------
- Event OnTimer(int aiTimerID) ; Cancel timer
- If aiTimerID == 1
- pgvScavverStartedRemoveAll.SetValue(0)
- ElseIf aiTimerID == 2
- ; Debug.MessageBox("RAD TIMER CLEANUP")
- pScavverActor.UnequipItem(pRoadGoggles, true, true)
- pScavverActor.UnequipItem(pSurgicalMask, true, true)
- If pScavver.GetItemCount(pRoadGoggles) > 1 ; Limit Scavver to having one extra to sell
- pScavver.RemoveItem(pRoadGoggles, 1, true)
- EndIf
- If pScavver.GetItemCount(pSurgicalMask) > 1 ; Limit Scavver to having one extra to sell
- pScavver.RemoveItem(pSurgicalMask, 1, true)
- EndIf
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("Scavver removed radiation gear.")
- EndIf
- RegisterForRadiationDamageEvent(Game.GetPlayer()) ; Catch the next radiation event
- ElseIf aiTimerID == 3
- float MovedDistance = pScavver.GetDistance(pScavverMarker)
- If pScavver.IsInInterior()
- pgvScavverIsIndoors.SetValue(1)
- pgvScavverWasStuck.SetValue(1)
- GetScavverUnstuck()
- EndIf
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("Scavver 10-second distance: " + MovedDistance)
- EndIf
- Utility.Wait(1)
- pgvScavverWasStuck.SetValue(0)
- If MovedDistance <= 100
- If !Utility.IsInMenuMode()
- If !pScavver.IsInDialogueWithPlayer()
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("SCAVVER IS STUCK... FIXING")
- pgvScavverWasStuck.SetValue(1)
- EndIf
- GetScavverUnstuck()
- EndIf
- EndIf
- EndIf
- If (pgvScavverWasStuck.GetValue() == 0) && (pgvScavverIsIndoors.GetValue() == 0)
- pScavverMarker.MoveTo(pScavver)
- pScavverTriggerVolume.MoveTo(pScavver)
- EndIf
- StartTimer(10, 3) ; Check the distance again in 10 seconds
- Else
- ; Timer ID is not 1-3, so do nothing
- EndIf
- EndEvent
- ; -----------------------------------------------------------------------------
- ; EVENT: ON ITEM EQUIPPED
- ; -----------------------------------------------------------------------------
- Event OnItemEquipped(Form akBaseObject, ObjectReference akReference)
- string DevMsg = ""
- If akBaseObject as Weapon
- DevMsg = "Scavver equipped a weapon."
- pScavverActor.DrawWeapon() ; Quick visual confirmation of weapon change (second draw in script)
- Else
- DevMsg = "Scavver equipped an outfit."
- EndIf
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification(DevMsg)
- EndIf
- EndEvent
- Function GetScavverUnstuck()
- float BumpDistance = 100
- float MinDistance = 100
- float MovedDistance = pScavver.GetDistance(pScavverMarker)
- float NowX = pScavver.GetPositionX()
- float NowY = pScavver.GetPositionY()
- float NowZ = pScavver.GetPositionZ()
- float ThenX = pScavverMarker.GetPositionX()
- float ThenY = pScavverMarker.GetPositionY()
- float ThenZ = pScavverMarker.GetPositionZ()
- float BumpX
- float BumpY
- float BumpZ
- float i = -1
- If Math.Abs(NowX - ThenX) > 0 ; If x axis movement before stuck
- If NowX > ThenX ; If x movement was positive
- BumpX = BumpDistance ; assign positive direction bump
- Else
- BumpX = i * BumpDistance ; else assign negative direction bump
- EndIf
- EndIf
- If Math.Abs(NowY - ThenY) > 0 ; If y axis movement before stuck
- If NowY > ThenY ; If y movement was positive
- BumpY = BumpDistance ; assign positive direction bump
- Else
- BumpY = i * BumpDistance ; else assign negative direction bump
- EndIf
- EndIf
- If pgvScavverIsIndoors.GetValue() == 1 ; If Scavver is in interior cell (vault)
- If pgvScavverStatusSniffer.GetValue() == 1
- Debug.Notification("SCAVVER IS INDOORS... FIXING")
- EndIf
- BumpZ = 1000 ; shoot him up out of the ground for handling
- pgvScavverIsIndoors.SetValue(0) ; and update the IsInterior global
- Else
- BumpZ = 60 ; else Z bump is balance between houses & hills
- EndIf
- pScavverMarker.MoveTo(pScavver, BumpX, BumpY, BumpZ) ; Move xmarker with offsets
- pScavverMarker.MoveToNearestNavmeshLocation() ; Move xmarker to nearest navmesh
- pScavver.MoveTo(pScavverMarker) ; Move Scavver to xmarker
- pScavverTriggerVolume.MoveTo(pScavver) ; Move trigger volume to Scavver
- EndFunction
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement