Jump to content

Can't get script to compile [F4SE]


Recommended Posts

Hi guys, I've been working on porting over a mod I really liked from Skyrim, and adapting it to the Fallout Universe with my own tweaks and writing. Note that this was a mod from LoversLab, and while it isn't inherently NSFW, it's contents (and thus the contents of this post) are mildly adult/suggestive in nature.

 

The documentation for the CK and papyrus have been all over the place and really hard to navigate, but I've more or less been able to get by. It definitely helps that its mostly just copy pasting good script and troubleshooting. It was going smooth until this one error in compiling a script I simply can't seem to figure out.

 

The main gimmick of the script is to create the functionality where a player can equip a particular item, but cannot unequip it. She will require a quest macguffin to release the outfit later on. I have the main functions on a framework script attached to a dummy quest, and the object calls the functions from that framework. So far the script runs alright, just without a lot of the features I want in it.

 

For the player to be "trapped" in the outfit, when the player attempts to unequip the outfit, the game should reequip it and display a message explaining why she was unable to unequip it. In the original mod for skyrim, the mod author's script did this by adding

Armor CurrentSuit ; remember last suit (for re-equip)

...truncated...

CurrentSuit = Game.GetPlayer().GetWornForm(0x00000004) as Armor ; 0x00000004 is SKSE's mask for slot 32 (body) 

to the outfit's OnEquip function.

 

This is my problem.

 

F4SE does not have a "GetWornForm" command, but it does have a "GetWornItem" command, which seems to work the same way. This is the version of the same line of code I have for Fallout:

Armor CurrentSuit ; remember last suit (for re-equip)

...truncated...

CurrentSuit = Game.GetPlayer().GetWornItem(3) as Armor

Where the "3" is the index for the Biped Slot 33 for BODY.

 

When I try to compile the script, however, I get the following error:

~\AppData\Local\Temp\PapyrusTemp\QST\qst_fw_scr.psc(96,48): cannot cast a actor#wornitem to a armor, types are incompatible

I can't seem to find any solution through google. My reading on the way "GetWornItem" works seems to indicate that i shouldn't have any issue at all, and googling the error itself doesn't yield any useful results. I've tried changing "as Armor" to a whole bunch of other things but I just get different errors with each of them. I'm at my wits end and I'd appreciate any help. I'm going to keep throwing my head at it myself, and will post updates if I find anything.

 

I can post the full code if it helps, though I feel like the problem is just in this line.

 

Link to comment
Share on other sites

The error is because `GetWornItem` returns a structure called `WornItem`. The `Item` property of WornItem is the weapon/armor form your looking for. http://www.creationkit.com/fallout4/index.php?title=WornItem_Struct_-_Actor

Armor CurrentSuit

Actor:WornItem worn = Game.GetPlayer().GetWornItem(3)
If (worn.Item is Armor)
    CurrentSuit = worn.Item
EndIf

The Actor:WornItem structure is nested instead the Actor type.

Link to comment
Share on other sites

Thanks, @Scrivener07.

 

I've plugged in your code as is, but I'm still getting a compiler error on the line:

CurrentSuit = worn.Item

It's a new error this time:

~\AppData\Local\Temp\PapyrusTemp\TIR\tir_fw_scr.psc(98,7): type mismatch while assigning to a armor (cast missing or types unrelated)

I'm afraid I don't fully understand why this is happening. It seems that it should work since it's pulling what could possibly be an "armor" and assigning it to an "armor". I think that means "types unrelated" is not the error here, but "cast missing", which i don't understand.

 

I'm sorry /: I hoped that I could take it from here and troubleshoot the new error, but I'm absolutely lost.

 

EDIT:

 

I've messed around with the code a little bit as follows:

Form CurrentSuit

Actor:WornItem worn = Game.GetPlayer().GetWornItem(3)
If (worn.Item is Form)
    CurrentSuit = worn.Item
EndIf

This compiles fine, but it breaks another segment of code here:

Armor Function GetCurrentSuit()
  if IsWearingSuit()
    return CurrentSuit
  else
    return none
  endif
EndFunction

This now drops the error:

~\AppData\Local\Temp\PapyrusTemp\TIR\tir_fw_scr.psc(82,4): cannot return a form from getcurrentsuit, the types do not match (cast missing or types unrelated)

on the line:

return CurrentSuit

I don't think I need that segment of code yet (though i'm not sure), so I've managed to compile it without that. I'm going to have to into the game to see how it works. I'll post another update later on when I've done that.

Edited by lonelyzentai
Link to comment
Share on other sites

Opps I think I did forget to cast the Form into an Armor.

Armor CurrentSuit

Actor:WornItem worn = Game.GetPlayer().GetWornItem(3)
If (worn.Item is Armor)
    CurrentSuit = worn.Item as Armor
EndIf

The item might be a weapon or an armor so you have to check its type.

Armor MaybeArmor
Weapon MaybeWeapon

Actor:WornItem worn = Game.GetPlayer().GetWornItem(3)
If (worn.Item is Armor)
    MaybeArmor = worn.Item as Armor
ElseIf (worn.Item is Weapon)
    MaybeWeapon = worn.Item as Weapon
Else
    Debug.Trace("unhandled type")
EndIf

Link to comment
Share on other sites

Thanks! That compiles just fine. Unfortunately the script doesn't seem to be working as expected. I couldn't get the object itself to call the function from the framework (it just did nothing) so I put the entire script from the framework into the object. It calls my log entries just fine, and it also displays the OnEquip and OnUnequip messages just fine. However the re-equipping is still bugged.

 

Farther down the line I call the CurrentSuit variable with:

Event OnUnequipped(actor akActor)
	If (akActor == game.GetPlayer())
		game.GetPlayer().EquipItem(CurrentSuit, false, true)
                tir_msg_unequip_failed.Show(0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f)
	EndIf
EndEvent

When running in game, the EquipItem command fails with this error in the log (Line 106 is the EquipItem line):

[04/28/2017 - 01:16:20PM] error: Cannot equip a None item
stack:
	[ (00000014)].Actor.EquipItem() - "<native>" Line ?
	[Item 10 in container  (00000014)].TIR:tir_suit_item.OnUnequipped() - "~\AppData\Local\Temp\PapyrusTemp\TIR\tir_suit_item.psc" Line 106

I've tried the following variations of the line, but I get the same error throughout:

game.GetPlayer().EquipItem(Self, false, true)
game.GetPlayer().EquipItem(Self as Armor, false, true)
game.GetPlayer().EquipItem(CurrentSuit as Armor, false, true)

I feel like the problem is in the "as Armor" part of the script - like the <native> tag in the error log is trying to tell me something about that. I thought it might be having problems storing the object data to the "CurrentSuit" variable, but it doesn't work with "Self" either, which confuses me. Shouldn't "Self" be a pretty straightforward reference? Or is this a problem with the way I have the object itself set up?

Edited by lonelyzentai
Link to comment
Share on other sites

I'm feeling a little overwhelmed by this whole thing - I'll post the full source, but I hope you don't feel obligated to help me out. I'm really thankful for your help thus far.

 

Credit to greyspammer from the loverslab forums for the original mod and script.

Scriptname TIR:tir_rubbersuit_item extends ObjectReference  
{Item script for the rubber catsuit (equip and unequip handling)}

; This is the framework for TIR-04 suit functions.

int TIR_Wearing = 0

int TIR_TimeTrapped = 0

int TIR_RemovalAllowed = 0

Armor CurrentSuit		; remember last suit (for re-equip)

GlobalVariable Property tir_fw_enabled auto
{Link to a  variable that can (temporarily) disable the framework}

Spell Property tir_EventSpell auto
{Link to the spell that confers the "rubber effect"}

Keyword Property TIR_Sealbreaker auto
{What is the keyword for the seal-breaker items (cheat items that bypass the lock)}

Message property tir_msg_equip_RubberCatsuit auto
{Message that is displayed when the player equips the rubber catsuit}

Message property tir_msg_unequip_failed_RubberCatsuit auto
{Message that is displayed when the player attempts to remove the rubber catsuit and fails}

Message property tir_msg_unequip_success_RubberCatsuit auto
{Message that is displayed when the player successfully removes the rubber catsuit}

FormList Property tir_rubbersuit_messages_stage1 auto
{Pick a random message from here while in stage 1}

FormList Property tir_rubbersuit_messages_stage2 auto
{Pick a random message from here while in stage 2}

FormList Property tir_rubbersuit_messages_stage3 auto
{Pick a random message from here while in stage 3}

GlobalVariable Property TimeScale auto
{Link to the TimeScale (for message interval calculation)}

GlobalVariable Property tir_Stage1Hours auto
{How many hours until stage 1 ends (and stage 2 begins)}

GlobalVariable Property tir_Stage2Hours auto
{How many hours until stage 2 ends (and stage 3 begins)}

GlobalVariable Property tir_MessageInterval auto
{Link to the for message interval calculation}

Faction Property tir_WearingSuit auto
{Link to the faction which the player will be a member of while wearing a suit}

; Logging function
Function log(String m)
  ;Debug.Notification("[TIR] "+m)
  Debug.Trace("[TIR] "+m)
EndFunction

; Logging function
Function glog(String m) Global
  ;Debug.Notification("[TIR] "+m)
  Debug.Trace("[TIR] "+m)
EndFunction

; Returns true when the player is wearing a "seal-breaker" item
; which is basically a cheat item
Bool Function IsRemovalAllowed()
  return (Game.GetPlayer().WornHasKeyword(tir_Sealbreaker)) || (TIR_RemovalAllowed == 1)
EndFunction

; Returns true if the player is wearing a rubbersuit
Bool Function IsWearingSuit() 
  return (TIR_wearing == 1)
EndFunction

Event OnEquipped(Actor akActor)
  if akActor == Game.GetPlayer()
	log ("player equipped suit")

		; Set the suit worn flag
		TIR_Wearing = 1
		log ("TIR_Wearing set to 1")

		; Remember form
		Actor:WornItem worn = Game.GetPlayer().GetWornItem(3)
		If (worn.Item is Armor)
    			CurrentSuit = (worn.Item) as Armor
		EndIf

		; Add player to suit faction
		Game.GetPlayer().AddToFaction(tir_WearingSuit)
		log ("Player added to tir_WearingSuit faction")

	       ; Show the "trap" message
		tir_msg_equip_RubberCatsuit.Show()
  endif
EndEvent

Event OnUnequipped(Actor akActor)
  if akActor == Game.GetPlayer()
	log ("Player Attempted to Unequip Suit")
	log ("Player is trapped in suit. Re-equipping.")
	Game.GetPlayer().EquipItem(CurrentSuit as Armor, false, true)
	tir_msg_unequip_failed_RubberCatsuit.Show()
  endif
EndEvent

This script is attached to the suit object itself. It was originally the framework script, but I couldn't get the suit's script to call the framework properly so I just dumped the whole framework into the suit and it seems to call the commands properly.

 

I'm going to keep messing with it - I'm thinking of trashing this script and starting from scratch. The thing is that the original mod had a larger array of features, and because I'm lifting a lot of the code and adapting it, I think I might be breaking some of the systems in the original author's framework. Also I don't really need a lot of the features he did.

  1. In his version of the mod, there were quite a number of varieties of armor that needed to trigger the same script, but in mine I only have the one.
  2. In Skyrim, the headpiece and the bodysuit had to be separate items, so he needed a script to make them work together. In Fallout I can bundle everything into one piece of armor.
  3. The original mod author had a long complex quest chain, and the framework accounts for the various interactions that occurs over the course of the quest - I envision my version of the quest to be more level-based, and passive. I'm hoping this makes scripting it easier.

I only need my version of the script to have the following features:

  1. Detect when the suit is equipped, so as to trigger the following:
    1. Display a flavor message to indicate the player's predicament.
    2. Starts a yet-to-be-written quest.
    3. Starts a timer to track how long the player has been in the suit.
  2. Detect when the suit has been unequipped, so as to trigger the following:
    1. Allow the suit to be unequipped if the player has a custom "Sealbreaker" item. (Keyword detection?)
    2. Else: Re-equip the suit immediately and display a flavor message explaining why the attempt failed.
  3. Assign a "Stage" to the player, based on how long the player has been in the suit.
  4. Send periodic messages to the player, based on what "stage" they are currently in. (to simulate thought)

And a few other not-fully-fleshed-out-ideas I had but don't have the ability to execute:

  1. Detect when the player has entered power armor, so as to send power-armor specific messages in addition to the periodic messages sent by default. (maybe an additional variable tir_wearingPA_stagex)
  2. Play custom sounds for movement, interaction, donning, doffing (successful), doffing (unsuccessful), and power armor use.
  3. Allow modification at workbenches.
  4. The suit object gradually regenerates the player's health, and if using Horizon, replenishes hunger and thirst. (I'm still trying to think of some negative features to balance out the armor.
  5. Display a custom visual overlay in first-person.
  6. One or two weapons that react differently depending on if the player is wearing the suit.

I'm still a really long way off /:

 

Though I'll admit, actually typing out the features I want to have makes the whole thing so much clearer for myself. I don't expect anyone to straight up write the script for me - I'm going to keep trying - but at the same time I appreciate any help or pointers in the right direction. Apart from a bit of tinkering in Quest's text adventure, this is the first time I'm doing anything to do with code. It's pretty daunting but I really, really love the logic of it all. It's just the language and the syntaxes that are a bit of a *censored*.

Edited by lonelyzentai
Link to comment
Share on other sites

  • Recently Browsing   0 members

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