Jump to content

Scripting issues with giving Armor other properties


SpacePirateCaine

Recommended Posts

Hi folks,

 

I've been recently working on a mod that adds a unique item following some of the plot originally established in Van Buren, the Experimental Stealth Boy technology originally developed by the BoS that spawned the Circle of Steel Faction. I'm modifying armor, to make it an equippable object, but for balance purposes want to make it have a few adverse affects, the first of which being to drain microfusion cells while it's in use, and be unusable otherwise.

 

In order to simulate ammo drain, I've tried to implement a bit of script, but I have no idea if I'm even on the right track. Could someone look at the following code and tell me how grievously wrong this is?

 

ScriptName CircleofSteelStealthScript

float timer

begin gamemode
if timer <= 0 player.RemoveItem AmmoMicroFusionCell 1 1
endif
if timer > 15
	if (GetItemCount AmmoMicroFusionCell <= 0)
		disable
	endif
	set timer to 0
endif
end

 

I have a feeling I've done something screwy here. Do I need to 'short AmmoMicroFusionCell'? The stealth field works fine, since I can do that from the GECK's inbuilt features, but it's giving me trouble otherwise.

 

I also have a Usage Monitor Effect applied to it, but still haven't managed to figure out how to implement an addiction counter and adverse effects, but I plan to cross that bridge when I get to it.

 

Any Ideas, oh wonderful much-smarter-than-I gentle folk?

Link to comment
Share on other sites

First off, you should remove the RemoveItem function from the condition of your first "if" statement, it should be on a new line.

 

There isn't anywhere in this script where you've actually changed the value of "timer", so you'll want to change it to use GetSecondsPassed. I'm not sure what this script is attached to, because there are some inconsistencies that mean it could pretty much be anything. If you let me know what it's attached to and exactly what you want it to do, then I'll be able to give you a little more help if you'd like.

 

Cipscis

Link to comment
Share on other sites

Cipscis, the reply is much appreciated. Let me give you a full rudown of what I've got so far:

 

At the moment, I've got this script attached to a modified copy of the BoS Recon armor, though ultimately I don't want to have it replacing armor, but to be an add-on (Backpack or somesuch that doesn't replace an existing armor slot). Still working out all the details on that.

 

I actually didn't see a 'GetSecondsPassed' in the timer entry of the GECK wiki functions list, so that's mostly a lack of good research on my part, I'm sure.

 

At the moment I've got the Recon Armor copied onto a new form, DR 0, weight 1, with an Object Effect applied that handles the Increased Sneak and Stealth Field, as well as UMON. I've also got these first few lines of script attached to the armor in the Script area.

 

My intention with this part of the script is for it to remove (drain) a microfusion cell every 15 seconds while equipped. I may increase or decrease this as necessary. If the player has 0 Microfusion Cells, then the Stealth Field/Increased Sneak effect should stop running, perhaps forcing an unequip.

 

Incidentally, I am also stumped about how to properly implement the UMON and make a player 'addicted' to a piece of equipment based on how often (or ideally, how long) the armor is equipped.

 

Is that enough information? I can try to elaborate more if necessary.

Link to comment
Share on other sites

Thanks, that's much clearer now.

 

GetSecondsPassed is the function usually used for making short-term timers (i.e. those that aren't long enough to use GameDaysPassed. There's an example of how to use it on its page on the GECK Wiki, and you can have a look at the code I've posted below for an example of how you might use it here.

 

Disable won't have any effect on an inventory item, so you'll probably want to use UnequipItem here. You'll also need to specify which reference to call GetItemCount on, and shouldn't "hard code" the player's reference as it's rather trivial to return the RefID of the Actor that has the scripted armour in their inventory.

 

For scripts on armours that should only run while the armour is equipped, a scripted Object Effect should be used as opposed to an Object Script. To do this, you'll need to create a new Base Effect with the "Script" Effect Archetype and the "Self" checkbox ticked, and apply it to an "Apparel" type Object Effect. Because Effect Scripts run on the target, as opposed to their origin, you will be able to use implied reference syntax to call reference functions on the Actor that has equipped the armour.

 

I would use a script something like this:

ScriptName CircleofSteelStealthScript

float fTimer

Begin ScriptEffectStart
set fTimer to 15
End

Begin ScriptEffectUpdate
if fTimer
	set fTimer to fTimer - GetSecondsPassed
else GetItemCount AmmoMicroFusionCell
	set fTimer to 15
	RemoveItem AmmoMicroFusionCell 1 1
endif
End

To make the effect no longer applied when the equipping Actor has no Microfusion Cells in their inventory, you could simply apply a condition of "GetItemCount AmmoMicroFusionCell >= 1" on the subject. This will cause the effect to cease when the Actor "runs out" of Microfusion cells, and start back up again once they have some more.

 

As far as I can make out, UMON is a dummy effect - it doesn't actually do anything in itself so I don't expect that you should be using it.

 

I haven't worked with addictions before, but it looks like they can only be applied normally to ingestibles. If you want to apply an addiction to this effect, then you're going to have to come up with some workaround - perhaps storing how long an Actor has had the armour equipped on via tokens (unplayable, therefore invisible, pieces of armour) which could be added every time an AmmoMicroFusionCell is removed. There are a few ways in which you could "fake" an addiction effect, but as far as I can tell, "real" addictions can only be applied to ingestibles.

 

Cipscis

Link to comment
Share on other sites

You're a life saver, Cipscis,

 

Thank you for your help. I'm poring over this code, and smacked myself in the head when I realized I should've been working with Base Effects all along. This will greatly help my progress, as long as I can really start wrapping my head around the code.

 

I'm starting to get a feel for it, but I'm still a little muddled on how to handle it all. I've started fiddling with the script and seem to have come up with the right script now. I took your idea of the UnequipItem script and implemented it in the ScriptEffectUpdate section, and it works like a charm. Here's the script, in its current form:

 

ScriptName CircleofSteelAmmoScript

float timer

Begin ScriptEffectStart
set timer to 15
End

Begin ScriptEffectUpdate
if (GetItemCount AmmoMicroFusionCell >= 1)
	if timer > 0
		set timer to timer - GetSecondsPassed
	else GetItemCount AmmoMicroFusionCell
		set timer to 15
		RemoveItem AmmoMicroFusionCell 1 1
	endif
else
	UnequipItem StealthBoyCircleofSteel
endif
End

 

There was actually one part of your script that was causing it to mess up, where it was calling 'if timer' without the '>0', but I managed to work that out without too much trouble.

 

I've updated the script name, since I'll be doing a few Base Effects that will lead up to the ultimate effect I'm trying to accomplish.

 

I'll continue to post scripts relevant to this mod as I continue, but at the moment, at least, I've got a working 'ammo draining armor' setup. I'm also looking around the current knowledge base on how to have a little popup (like the XYZ unequipped) display a custom message, like "The Experimental StealthBoy has run out of power" or something of the like, and maybe a floating Microfusion Cell count, though these are low-priority cosmetic things.

 

Next step, getting it to display in-world as a stealthboy, instead of as armor.

Link to comment
Share on other sites

Oops, sorry about missing out that " > 0". Looks like I forgot to proof it before I posted it, lol. I notice that I've also tried to include a condition in an "else" statement, which doesn't take a condition. I've also noticed that the ScriptEffectStart block isn't really required, as the ScriptEffectUpdate block will set "timer" to 15 when it first runs anyway, and GetSecondsPassed will return 0 in this first iteration anyway so the ScriptEffectStart block really isn't adding anything to the script at all.

 

You can safely remove the " >= 1" part of your GetItemCount condition, as GetItemCount will never return a value lower than 0. Keeping this in mind, there are two different ways in which you could use the script. Here is one:

ScriptName CircleofSteelAmmoScript

float timer

Begin ScriptEffectUpdate
if GetItemCount AmmoMicroFusionCell
	if timer > 0
		set timer to timer - GetSecondsPassed
	else
		set timer to 15
		RemoveItem AmmoMicroFusionCell 1 1
	endif
else
	UnequipItem StealthBoyCircleofSteel
endif
End

Here is the other:

ScriptName CircleofSteelAmmoScript

float timer

Begin ScriptEffectUpdate
if timer > 0
	set timer to timer - GetSecondsPassed
elseif GetItemCount AmmoMicroFusionCell
	set timer to 15
	RemoveItem AmmoMicroFusionCell 1 1
else
	UnequipItem StealthBoyCircleofSteel
endif
End

As you can see, these scripts differ in that the first one will unequip the item as soon as there are no Microfusion Cells left, and the second will unequip the item if the timer is up and there are no Microfusion Cells first. I get the feeling that you'll want to use the first version, but I thought I'd make sure you were aware of the other possible implementation anyway.

 

If you want a message to show up, then you'll want to use the ShowMessage command. You can use the available formatting notation to include variables within the message too, if you want to display the number of Microfusion Cells remaining, for example.

 

Cipscis

Link to comment
Share on other sites

Thanks for the pointers, it's definitely helped me work out the basic points of scripting here, and I've decided to go with that first option. It works like a charm, and I thank you very much for your help. It does drain one microfusion cell immediately on equip, and one in the following 15 seconds, so if you only have 2 cells, you only get 15 seconds instead of 30, but I'll call that an acceptable loss.

 

As I don't want to mess around too much with the random popup messages in the upper left corner, I'm going to do some research into adding another small part to the HUD that displays Cell count while the StealthBoy is in use.

 

In the meantime, I've managed to put together a pretty reliable script for Addiction. Turns out you can set up an Actor Effect Addiction just as you would for a chem, by following the examples of the existing chems, without having to 'simulate' much at all. The major issue is getting the addiction to happen, but I've set it up as a random (very small) chance to affect the player every 45 seconds of usage. This is the code:

 

ScriptName CircleofSteelAddictionScript

float timer
short sRandomNumber

Begin ScriptEffectUpdate
if (IsSpellTarget WithdrawalStealth == 0)
	if timer > 0
		set timer to timer - GetSecondsPassed
	else
		set timer to 45
		set sRandomNumber to GetRandomPercent
		if sRandomNumber < 2
			CastImmediateOnSelf WithdrawalStealth
			ShowMessage CircleofSteelAddiction
			ApplyImageSpaceModifier Addiction01ISFX
			PlaySound FXCrippleHead
		endif
	endif
endif
End

(I lifted some script from the 'Variable Nudes' thread that was up here not so long ago, so thank you again, if indirectly)

 

If I'm missing anything, please let me know. I also managed to make sure that it doesn't display the addiction message again, in the event that you already have the withdrawal effect. As I'm billing the 'withdrawal' as neurological damage, I'm actually glad that it doesn't behave exactly like the others, so this way the player will still be affected, regardless of using the equipment or not.

 

I do have one last issue with the actual usage of the item: I need to work out how to play a different sound when equipping the armor from when picking it up. I've noted that at the moment it plays the same 'pickup' noise when equipping. The sound is subtle enough that I think the 'OBJStealthBoyActivate' sound should drown it out when activating, but so far the sound only seems to want to play after leaving the PIPBoy. Any thoughts?

Link to comment
Share on other sites

Silly me... That's why I had a ScriptEffectStart block - so that a Microfusion Cell wouldn't be removed when the item was equipped. Sorry about that, I'd forgotten why I'd done that when I came back to look at it for a second time.

 

I'm not sure if adding extra elements to the HUD, but you could have a look at the XML that controls the HUD and FOSE's GetUIFloat, SetUIFloat and SetUIString functions as a place to start your research.

 

The major issue is getting the addiction to happen
Yeah, this is what I meant when I said that you'd have to simulate an Addiction - you can't use the same method of applying it as Ingestibles use.

 

I'm not really sure how "Equip Sounds" are governed for Armour, but it looks like the "Pickup Sound" might be used for the "Equip Sound" and the "Putdown Sound" used for the "Unequip Sound". You could probably get around this by using two different Armours - one which appears in the world and has a "Pickup Sound" defined, and the other which appears in the inventory and has no "Pickup Sound" defined. You could use scripts like these to swap the two armours back and forth depending on their location:

ref rContainer

Begin OnAdd
set rContainer to GetContainer
rContainer.AddItem InventoryItem 1 1
RemoveMe
End

Begin OnDrop
Disable
PlaceAtMe WorldItem 1 1
End

Cipscis

Link to comment
Share on other sites

Awesome, thank you.

 

I was having some trouble getting it to run, and then got sidetracked for a few days, but ultimately realized that the script you just gave me works not as an object effect, but when applied as an object script directly to the object itself. Now it works like a charm. Thank you so much for your help.

 

I have noticed one issue, however. Because of the 'drop' call there, it actually hands the inventory item over *and* drops an identical one when the player attempts to either give it to a companion or sell it. I'm applying the if GetContainer == 0 condition to it, and working on making sure that the dummy gets placed in the appropriate container.

 

Otherwise, I'm still working out the details of how to add a counter to the HUD, but failing rectification of the above issue, I will just probably release the mod as is. I really appreciate all the help you've given me, and I'll be sure to give a thank you in the official release as well. If I can't work out anything on the HUD, expect to see it pop up on the nexus sometime this week, at least in its Beta.

 

I'm having one or two issues with the game loading slowly, etc. But I'm not sure if that's an issue with mod optimization, or if it's just my computer which hasn't always really agreed with FO3 in the first place. I'll need some people to help test out the mod to make sure it's fully functional, but I'm sure there's a better place to go about that.

 

Anyway, many thanks once again.

Link to comment
Share on other sites

Alright, so after much fiddling with the drop script, I'm stumped yet again (I blame my inexperience with scripting, but I'm beginning to wonder if there's an elegant solution for this at all).

 

In order to make sure that upon transferring the object to another container (be it teammate inventory or just a random box), it doesn't also drop a Dummy object on the ground, I've used if GetContainer == 0 like so:

 

ScriptName CircleofSteelDummyDrop

Begin OnDrop
Disable
if GetContainer == 0
	PlaceAtMe StealthBoyCircleofSteelDummy 1 1
endif
End 

This works pretty smoothly for my purposes, but it still leaves me with issues upon actually transferring the object to another container. (i.e. it transfers the inventory object, therefore playing the 'pickup/activate' sound for the inventory item, as opposed to the dummy pickup sound, like I require it to).

 

I've tried combinations using an else followed by Disable and AddItem functions (so if GetContainer returns another value aside from 0, it runs the script), but nothing's doing quite what I need. The closest I've managed to get was the following:

 

ScriptName CircleofSteelDummyDrop

ref rContainer

Begin OnDrop
Disable
if GetContainer == 0
	PlaceAtMe StealthBoyCircleofSteelDummy 1 1
else
	set rContainer to GetContainer
	rContainer.RemoveItem StealthBoyCircleofSteel 1 1
	rContainer.AddItem StealthBoyCircleofSteelDummy 1 1
endif
End 

Which I have a feeling is only deceiving me into thinking I'm on the right track. What this does is transfer the StealthBoy (Inventory item) to the target container (With the 'activate' sound that I'm trying to avoid), then when I try to get it back, it switches it with the Dummy once - Apparently finally heeding my rContainer.Remove/Add script without transferring to my inventory, then the dummy transfers over correctly.

 

What I'm really trying to do is upon transferring the StealthBoy to another container, it should disable, or whatever is proper in this instance, and place the dummy in the target container without playing the pickup/activate sound for the inventory item.

 

I so far have been pretty unsuccessful in achieving this.

 

Crikey, this whole thing is extremely convoluted just for the aesthetics of having one sound play as opposed to another. I hope someone can steer me back on the right path. Am I overcomplicating things? Or is this actually a pretty demanding feat of scripting for a deceptively simple concept?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

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