Jump to content

Advanced List Use and Ref Passing


Recommended Posts

So, in making the Alt Start series of mod something that was truly worth using over and over, I wrote a series of relatively (for me anyway) complex scripts to handle dynamically chosen and randomized selections of weapons and starting equipment for players. I spent quite a lot of time getting the things to work correctly, helped along by people from the community (I forget now who all I had help from, as I wrote these almost 2 years ago).

 

In the update for Fallout: New Vegas, I nearly rewrote the entire mod (from the Fallout 3 version) to be more efficient and to add new features. Since I'm done with the mod, and I learned quite a bit from this work, I figured I'd share what I've learned with others, in the hopes that this information might help someone else with a project of theirs.

 

So here's just the initial weapon adding script, which adds a primary weapon based on the player's guns skill, and an option choice of which type of weapon they prefer.

if (AltStart.SkillGuns > 0) && (AltStart.weapChoice == 0)		;handles any choice; DEFAULT
set rWeapList to StartWeapGuns
elseif (AltStart.SkillGuns > 0) && (AltStart.weapChoice == 1)	;handles pistol choice
set rWeapList to StartWeapPistol
elseif (AltStart.SkillGuns > 0) && (AltStart.weapChoice == 2)	;handles rifle choice
set rWeapList to StartWeapRifle
elseif (AltStart.SkillGuns > 0) && (AltStart.weapChoice == 3)	;handles shotgun choice
set rWeapList to StartWeapShotgun
endif

if (AltStart.SkillGuns > 0)
; printc "adding gun"
;set variables for use in this block (reused in each block)
	set healthBonus to (GetRandomPercent * (AltStart.bonAmount) / 99)
	set healthPenalty to (GetRandomPercent * (AltStart.penAmount) / 99)
	set sItemHealth to ((Player.GetAV Repair - healthPenalty + healthBonus) / 100)
	set sItemIndex to (AltStart.SkillGuns + AltStart.HistBg) - 1
	set rListName to ListGetNthForm rWeapList sItemIndex					;get the list with weapons at the level to be added (poor, moderate, decent, good)
	set sListLength to ListGetCount rListName						;get the length of the retrieved list
	set randVal to ((GetRandomPercent * sListLength) / 99)					;get a random value for retrieval of a weapon from the weapons list
	set rItemBase to ListGetNthForm rListName randVal					;get the weapon to be added from the list using the calculated random value
	Player.AddItemHealthPercent  rItemBase 1 sItemHealth 1
	set rAmmoType to GetWeaponAmmo rItemBase						;get ammo type and clip size for the added weapon
	set sClipSize to GetWeaponClipRounds rItemBase
;determine how much ammo should be added for the weapon
	if (sItemIndex == 0)
		set sNumClips to 1
	else
		set sNumClips to sItemIndex
	endif
	set randVal to ((GetRandomPercent * sClipSize) / 99)
	if (sClipSize > 12)
		set sAddAmmo to ((sClipSize * sNumClips) + randVal)
	elseif (sClipSize > 2)
		set sAddAmmo to (((sClipSize * sNumClips) + randVal) * AltStart.GunsAmmoMult1)
	else
		set sAddAmmo to (((sClipSize * sNumClips) + randVal) * AltStart.GunsAmmoMult2)
	endif
	;if Player has scrounger perk (added by certain histories), add more ammo to them
	if (Player.HasPerk Scrounger)
		set sAddAmmo to sAddAmmo + ( 2 * ((GetRandomPercent * sClipSize) / 99))
	endif
;find out what type of ammo the gun uses (list or ammo)
	if (GetType rAmmoType == 41)											;is an ammo type, can continue as normal
		set sAddAmmo to (sAddAmmo * AltStart.sDifficultyMult)
		Player.AddItem rAmmoType sAddAmmo 1
	elseif (GetType rAmmoType == 85)										;is a list of ammo, must do additional work
		set rAmmoList to rAmmoType
		set sListLength to ListGetCount rAmmoList
		set sCountLength to 0
		Label 10
		set rAmmoType to ListGetNthForm rAmmoList sCountLength
		if (sCountLength == 0)											;for first ammo in list, handle as normal
			set sAddAmmo to (sAddAmmo * AltStart.sDifficultyMult)
			Player.AddItem rAmmoType sAddAmmo 1
		else													;for all the rest of the ammos
			set randVal to GetRandomPercent							;get a random value
			if (randVal < AltStart.specialAmmoChance)					;chance of getting special ammo
				set sAddAmmo to ((sClipSize + randVal)/10) * (AltStart.LuckBonus/4)	;Reduces amount of special ammo
				Player.AddItem rAmmoType sAddAmmo 1
			endif
		endif
		set sCountLength to (1 + sCountLength)
		if (sCountLength < sListLength)
			Goto 10
		endif
	endif
;determine if the Player should get a weapon mod for this weapon
	set sCountLength to 1
	set sModChance to AltStart.sWeapModChance
	Label 20
	set rWeapMod to GetWeaponItemMod sCountLength rItemBase
	if (rWeapMod)
		set randValTwo to GetRandomPercent
		if (randValTwo <= sModChance)
			Player.AddItem rWeapMod 1 1
			set sModChance to sModChance + 6
		endif
	endif
	set sCountLength to (1 + sCountLength)
	if (sCountLength < 4)
		Goto 20
	endif
set hasGun to 1
endif

 

It obviously does more than just that, so I'll try to just walk through what each section does.

 

set healthBonus to (GetRandomPercent * (AltStart.bonAmount) / 99)
set healthPenalty to (GetRandomPercent * (AltStart.penAmount) / 99)
set sItemHealth to ((Player.GetAV Repair - healthPenalty + healthBonus) / 100)
set sItemIndex to (AltStart.SkillGuns + AltStart.HistBg) - 1
set rListName to ListGetNthForm rWeapList sItemIndex						;get the list with weapons at the level to be added (poor, moderate, decent, good)
set sListLength to ListGetCount rListName							;get the length of the retrieved list
set randVal to ((GetRandomPercent * sListLength) / 99)						;get a random value for retrieval of a weapon from the weapons list
set rItemBase to ListGetNthForm rListName randVal						;get the weapon to be added from the list using the calculated random value
Player.AddItemHealthPercent  rItemBase 1 sItemHealth 1
set rAmmoType to GetWeaponAmmo rItemBase								;get ammo type and clip size for the added weapon
set sClipSize to GetWeaponClipRounds rItemBase

This section starts off by determining random values by which to calculate the item's health. The AltStart.bonAmount and AltStart.penAmount are quest variables that are set by the player's choice of what history they use.

 

This line

set sItemIndex to (AltStart.SkillGuns + AltStart.HistBg) - 1

uses the player's history choice to determine what level of guns the player can get. Guns have been divided into four groups based on how good the gun is.

 

The next section is commented, so I will just describe what it does. Once the script has the list with the weapons in it, it finds the length of that list, and then generates a random value between 0 (first index of the list) and the last index of the list. That way the number will fall within the range of the number of items on the list, ensuring that we always give an item. Once it has a number it sets the item in that index to a variable, from which we can use it as though we were referring to the form name of that item. Then it just gets added to the player with the previously calculated health value.

 

The last two lines of that section get the ammo type the weapon uses and the number of rounds the weapon holds in each clip for use in later sections.

 

;determine how much ammo should be added for the weapon
if (sItemIndex == 0)
set sNumClips to 1
else
set sNumClips to sItemIndex
endif
set randVal to ((GetRandomPercent * sClipSize) / 99)
if (sClipSize > 12)
set sAddAmmo to ((sClipSize * sNumClips) + randVal)
elseif (sClipSize > 2)
set sAddAmmo to (((sClipSize * sNumClips) + randVal) * AltStart.GunsAmmoMult1)
else
set sAddAmmo to (((sClipSize * sNumClips) + randVal) * AltStart.GunsAmmoMult2)
endif
;if Player has scrounger perk (added by certain histories), add more ammo to them
if (Player.HasPerk Scrounger)
set sAddAmmo to sAddAmmo + ( 2 * ((GetRandomPercent * sClipSize) / 99))
endif

The first check for sItemIndex == 0 just lets us know if the weapon is for the lowest tier weapons, in which case you only get a clip of ammo for it, otherwise the number of clips is based on the item index number (duh, huh?).

 

Then we get a random number less than or equal to a full clip of ammo for this weapon. Next we check for clip sizes, adding ammo based on the clip size, with lower clip size weapons getting a higher proportional number of rounds per clip size. This is just to ensure that a player with a single shotgun gets enough rounds to actually survive at least their first encounter with enemies (hopefully). The GunsAmmoMult* values are set in an initialization script along with all other quest variables. A final check for the Scrounger perk adds some extra ammo.

 

This next section was added new to the Fallout: New Vegas version, due to the fact that it uses ammo lists instead of ammo forms. It does however account for weapons that do use a single ammo form, such as the Fat Man or any mod added weapons.

;find out what type of ammo the gun uses (list or ammo)
if (GetType rAmmoType == 41)											;is an ammo type, can continue as normal
set sAddAmmo to (sAddAmmo * AltStart.sDifficultyMult)
Player.AddItem rAmmoType sAddAmmo 1
elseif (GetType rAmmoType == 85)										;is a list of ammo, must do additional work
set rAmmoList to rAmmoType
set sListLength to ListGetCount rAmmoList
set sCountLength to 0
Label 10
set rAmmoType to ListGetNthForm rAmmoList sCountLength
if (sCountLength == 0)											;for first ammo in list, handle as normal
	set sAddAmmo to (sAddAmmo * AltStart.sDifficultyMult)
	Player.AddItem rAmmoType sAddAmmo 1
else													;for all the rest of the ammos
	set randVal to GetRandomPercent									;get a random value
	if (randVal < AltStart.specialAmmoChance)							;chance of getting special ammo
		set sAddAmmo to ((sClipSize + randVal)/10) * (AltStart.LuckBonus/4)			;Reduces amount of special ammo
		Player.AddItem rAmmoType sAddAmmo 1
	endif
endif
set sCountLength to (1 + sCountLength)
if (sCountLength < sListLength)
	Goto 10
endif
endif

So the first check is for an ammo form type, in which case we just add the calculated number of rounds and we're done. For an ammo list, it gets more complicated, because it needs to have a chance to add some of each type of ammo on the list. This again accounts for all mod added ammo types, and will iterate through the list until the end. As you can see though, the first ammo type in the list is assumed to be the default ammo type, or normal ammo for that weapon, and gets added like it would without a list present.

 

The sDifficultyMult variable is an unimplemented difficulty mod designed to allow players to change how hard they want their game to be at the start. specialAmmoChance is set to a 33 percent chance (for each iteration through) of getting a special ammo type. Then it finds a random amount, with a relation to Luck playing into how much you get.

 

This last section is newest, and undocumented. I referenced Pelinor's The Weapon Mod Menu for how to access the weapon mod data for weapons. There is an almost complete lack of documentation on these NVSE functions, which makes them rather difficult to use.

set sCountLength to 1
set sModChance to AltStart.sWeapModChance
Label 20
set rWeapMod to GetWeaponItemMod sCountLength rItemBase
if (rWeapMod)
set randValTwo to GetRandomPercent
if (randValTwo <= sModChance)
	Player.AddItem rWeapMod 1 1
	set sModChance to sModChance + 6
endif
endif
set sCountLength to (1 + sCountLength)
if (sCountLength < 4)
Goto 20
endif

We first set our count variable to 1, then get the chance for mods, another one of those unimplemented variables that could allow players the ability to select the chance for getting weapon mods. The GetWeaponItemMod function returns the first mod item used by that weapon. More accurately, the function returns the item at the index number provided in the form

set rItem to GetWeaponItemMod int:int item:ref

Since I'm using a variable at the int, I can increment it by one through a loop and move through each weapon mod slot on the weapon. It also performs a check to ensure that the weapon mod returned is a valid item, to make sure we don't add a null item, which would probably crash the game.

 

As I'm writing this I see a mistake in here, the line

set sModChance to sModChance + 6

should actually be

set sModChance to sModChance [b]-[/b] 6

, in order to make the chance for getting a subsequent mod smaller, not greater. That's a whoops on my part.

 

 

Well that's how it works. This is the most complex part of the mod. The armor adding script is similar, without all the weapon specific stuff. Armors just get health values, and are equipped after being added. Not even sure if anyone cares about this or will use it, but I figured I had it, I'd put it out here for anyone to look at.

 

If you have questions, just ask. If you'd like to see the full code, you can go check out the mod here and look at the code in context.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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