Jump to content

Photo

Need Help With Scripting


  • Please log in to reply
10 replies to this topic

#1
RipperV

RipperV

    Regular

  • Members
  • PipPip
  • 70 posts
What I want to do is create a hand-to-hand weapon (knuckles) that when drawn adds an imagespace modifier, slows time, increases player speed (inverse to time speed), increases the healing rate, and adds unarmed damage. IE player draws fists, and the screen goes red and time slows, but the player's speed stays the same (inverse of time speed), and the player is stronger and has an increased healing rate. I'd also like to add a jumping height multiplier, but I can't find the function for that (SetActorValue JumpMult X?)

What I have so far is this (Please note, it's my first script. I know limited VB, which has been a little help):

scn RageVisualFX

Float fltTimeSpeedEffect = 0.5 ; multiplyer for timespeed. Player speed should remain the same (inverse)
Short srtExtraMeleeDmg = 20 ; Extra hand-to-hand damage ammount
Float rfltBaseHealRate ; Initial player heal rate. Tripled on activate.
Float fltHealRateMult = 3 ; Rate to multiply healing by

Begin OnStartCombat ; When player enters combat (hopefully when weapon is drawn)

imod 01000EA7 ; Add VisualFX
sgtm fltTimeSpeedEffect ; Slow time

Float TimeSpeedInverse = (1 / fltTimeSpeedEffect)
Player.SetActorValue SpeedMult TimeSpeedInverse ; Set Speed to inverse of fltTimeSpeedEffect

Player.SetActorValue UnarmedDamage srtExtraMeleeDmg ; Add bonus hand-to-hand damage

Set rfltBaseHealRate To Player.GetActorValue HealRate ; Save the players heal rate.
If rfltBaseHealRate == 0 ; No heal rate to begin with
Player.SetActorValue HealRate fltHealRateMult ; Set rate to multiplyer
Else
Float HealMultiplyer = (rfltBaseHealRate * fltHealRateMult)
Player.SetActorValue HealRate HealMultiplyer ; Else multiply heal rate
EndIf

End

Begin OnCombatEnd ; When player exits combat (hopefully when weapon is sheathed)

rimod 01000EA7 ; Remove VisualFX
sgtm 1 ; Reset Time to normal
Player.SetActorValue SpeedMult 1 ; Set Speed to normal

Player.SetActorValue UnarmedDamage 0 ; Remove bonus hand-to-hand damage

Player.SetActorValue HealRate rfltBaseHealRate ; Reset heal rate

End


In game, it does nothing :| Edit: I also tried a version that used ShowMessage when combat starts/ends, but that also didn't do anything :|

#2
cmal

cmal

    Enthusiast

  • Members
  • PipPip
  • 161 posts
First and foremost, Fallout's scripting language does not assign values to variables like conventional programming languages. You can't set a variable when you declare it, for one. You have to use a separate line using the command Set (ie: Set fltfltTimeSpeedEffect to 0.5). That should take care of most of your problems.

Next, you should store all of your original actor values in a variable. If you use, for example, Player.SetActorValue UnarmedDamage 0, it will set your unarmed damage to 0 even if it was non-zero before your script ran. If you happened to have the Iron Fist Perk, you just erased its effect.

Thirdly, how is this script running? Is it attached to a weapon (Object), running in the background (Quest), or something like a Perk or ability (Effect)?

OnStartCombat and OnCombatEnd will only trigger when the game enters/leaves combat mode. Whether your weapon is drawn or not is irrelevant. Use IsWeaponOut in an if structure in your blocks to check if your weapon is out when you're in combat. I don't think its necessary to check once you are out of combat. And you should add a switch variable so that the code in the game blocks only run the first time and then reset when the effect ends. Scripts in Fallout are basically run every frame, so its like a giant while loop.

That's all I can think of for now. Try these out and post your results. I also suggest you look at the GECK Wiki and read Cipcis' excellent scripting tutorial.

#3
gsmanners

gsmanners

    Faithful poster

  • Members
  • PipPipPipPip
  • 2,333 posts
Changing "speedmult" will not affect the player until you change their equipment (and you can't reasonably do that in a script without FOSE). It's also highly problematic to slow down the time base since that throws off spell durations and who knows what other scripts and mods you just made fail to function properly because they rely on that timer?

Using an ISFX is a good idea, but you can use it by name in a script. You don't have to use the hex code.

#4
RipperV

RipperV

    Regular

  • Members
  • PipPip
  • 70 posts
Ok, new version, but untested... I've removed trying to play with health regeneration rate, too much work for something I won't need. Also used OnEquip instead, will add for player only later. Also have a boolean check to see if it's already active. Does the GECK have an If __ and __ statement? Nested If statements are fugly :|

Edit:Tested. still doesnt work all the way, but I think I got player speed to move. Also have MeleeDamage changed to UnarmedDamage.

cmal: As a weapon. When the knuckles are drawn, the effect starts.

gsmanners: Theres a bullet time mod that slows time quite nicely :) Thats pretty much what I want to copy. Also added EditorID naming for the imod, dunno why the GECK told me that didn't work earlier. I also believe I read somewhere that there's a console command to change speedmult, so I'd expect that to work as well.

scn RageVisualFX

Float TimeSpeedMult
Float MeleeDmgMult

Float BaseMeleeDmg
Float BaseSpeedMult

Int Active ;Boolean, is effect active? 0 No, 1 Yes

Begin OnEquip
Set TimeSpeedMult To 0.25 ;1/4 speed time
Set MeleeDmgMult To 5 ;MeleeDmg * 5

If Player.IsWeaponOut == 1
If Active == 0 ; If Drawn and Effect Inactive,
;Declare a new float to use for math
Float Math
Set Active To 1

;Gather base data
Set BaseMeleeDmg To Player.GetActorValue MeleeDamage
Set BaseSpeedMult To Player.GetActorValue SpeedMult

;Do Some Maths and Set New Values
sgtm TimeSpeedMult ;Slow time

Set Math To (BaseSpeedMult / TimeSpeedMult) ;Calculate new playerspeed
Player.SetActorValue SpeedMult Math ;Set new speed (Inverse of slowdown)

Set Math To (MeleeDmgMult + (BaseMeleeDmg * MeleeDmgMult)) ;Example dmg 0 -> 5, dmg 1 -> 10, dmg 2 -> 15
Player.SetActorValue MeleeDamage Math ;Set new melee damage

;Add IMOD
imod RIPRageFX
EndIf
ElseIf Player.IsWeaponOut == 0
If Active == 1 ;If Sheathed and Effect is Active,

sgtm 1 ; Reset Time to whatever it was

Player.SetActorValue SpeedMult BaseSpeedMult ;Reset old multiplier

Player.SetActorValue MeleeDamage BaseMeleeDmg ;Reset old melee dmg

;Remove IMOD
rimod RIPRageFX
Set Active To 0
EndIf
EndIf
End



#5
Cipscis

Cipscis

    Scripter

  • Premium Member
  • 1,275 posts
Please use "code" or "codebox" tags when posting scripts, as this conserves indentation and causes them to be shown in a fixed-width font. Since you say you have some experience with VB I'm sure you know how to indent your scripts, but just in case you're not entirely sure here is a utility that can do it for you, as well as check for several structural errors - Script Validator.

Changing "speedmult" will not affect the player until you change their equipment (and you can't reasonably do that in a script without FOSE).

While it's true that changing "SpeedMult" is more problematic than making changes to other AVs, it is still feasible without FOSE. As far as I know, these are the events that will cause an actor's speed to be recalculated:
  • Drawing or holstering a weapon
  • Toggling sneak mode
  • Any changes to one of the two mobility AVs: "LeftMobilityCondition" and "RightMobilityCondition"
Given that drawing or holstering a weapon can cause a recalculation of an actor's speed, and that AV should be changed whenever this event occurs, extra code may not be required.

Does the GECK have an If __ and __ statement? Nested If statements are fugly :|

You can use a logical AND for this via the "&&" operator. However, whenever possible it is best to use nested conditions in Fallout 3 script for efficiency reasons. Conditions in Fallout 3 scripts are not very well optimised, so if the first part in a condition utilising a logical AND evaluates to false, the rest of the condition will still be evaluated. Because of this, nested conditional statements are more efficient. However, when using more complicated blocks of conditional statements (i.e. those utilising "else"/"elseif" statements) use of the "&&" operator may be unavoidable.

At the moment, because you're using a OnEquip block, your script will only run once whenever the weapon is equipped by an actor. Instead, you'll want to use three blocks:
  • An OnEquip block to set the value of a variable that stores information on whether or not the weapon is equipped
  • An OnUnequip block to reset the value of the same variable
  • A GameMode block to run code that depends on conditions such as whether or not the weapon is drawn

In Fallout 3 scripts, variables should be declared at the the top of the script, outside of any Begin/End blocks, so you'll want to move your declaration of the "Math" variable on line 18 to the top of the script with your other variable declarations. It's also worth noting that, when checking boolean values such as the return value of IsWeaponOut, the "== 1" is unnecessary and actually makes the script less efficient. It is also more efficient to use the following structure in the place of "== 0":
if <condition>
else; if <condition> == 0
It's also worth noting that when dealing with exactly opposite conditions, "else" statements should be used instead of "elseif" statements. For example, the second example below is more efficient than the first:
if <condition>
elseif <condition> == 0
if <condition>
else
I'm not sure if you can ensure that there will only ever be one instance of this weapon, and that only the player will ever be able to equip it, then you don't need to worry about this, but otherwise there are a few changes that you should make. Basically, you should generalise most of the script by using a "ref" variable to store the return value of GetContainer so that the functions that you call will be applied to the actor that has equipped the weapon. If you do this, then you'll obviously want to make a few changes so that the same code doesn't run on the player as on NPCs. Basically you'll want to change the speed handling so that the speed of the game only changes when the player equips the weapon, and the ImageSpace Modifier will only be applied if the player equips the weapon.

Sorry if I've made any typos or if this post is difficult to follow. I've been watching a movie while I wrote it so there might be a few instances of qwertial aphasia mixed in there.

Cipscis

#6
RipperV

RipperV

    Regular

  • Members
  • PipPip
  • 70 posts
Oooh, thanks, I'll get back to work :)

Edit: I <3 you

Got it to work mostly :)
Problem is, speed is set when holstered, but time and imod are set when drawn (like they should be). Speed is set in the wrong end.

Edit2: Oh, and are there functions? I'd like to make a sub for turning off the effects, since the same code is called twice...

scn RageVisualFX

Float TimeSpeedMult;Ammount to decrease speed
Float MeleeDmgMult;Ammount to increase damage

Float BaseMeleeDmg;initial Damage multiplier
Float BaseSpeedMult;initial Speed multiplier

Float Math;Used for calculations

Int Active;Boolean, is effect active? 0 No, 1 Yes

Begin OnEquip;Declare initial values
	If GetContainer == Player;If it's the player, start declarations
		Set TimeSpeedMult To 0.25;1/4 speed time
		Set MeleeDmgMult To 20;MeleeDmg + 20
		If Player.IsWeaponOut;Player has already drawn weapon (equipped while drawn)
			Set Active To 1
		Else;Player has equipped while holstered
			Set Active To 0
		EndIf
	Else
		Set Active To 2;NPC
	EndIf
End

Begin GameMode
	If Active != 2;If it's not an NPC equipping it,
		If Player.IsWeaponOut
			If Active == 0; If Drawn and Effect Inactive,
				Set Active To 1
	
;Gather base data
				Set BaseMeleeDmg To Player.GetActorValue UnarmedDamage
				Set BaseSpeedMult To Player.GetActorValue SpeedMult
	
;Do Some Maths and Set New Values
				sgtm TimeSpeedMult;Slow time
	
				Set Math To (BaseSpeedMult / TimeSpeedMult);Calculate new playerspeed
				Player.SetActorValue SpeedMult Math;Set new speed (Inverse of slowdown)
	
				V EDIT V
				Player.ModActorValue UnarmedDamage MeleeDmgMult;Add melee damage
	
;Add IMOD
				imod RIPRageFX
			EndIf
		Else
			If Active == 1;If Sheathed and Effect is Active,
	
				sgtm 1; Reset Time to whatever it was
		
				Player.SetActorValue SpeedMult BaseSpeedMult;Reset old multiplier
		
				Set Math To (-1 * (Player.GetActorValue UnarmedDamage - MeleeDmgMult));Remove extra damage
				Player.ModActorValue UnarmedDamage Math;Reset old melee dmg
				
		;Remove IMOD
				rimod RIPRageFX
				Set Active To 0
			EndIf
		EndIf
	EndIf
End

Begin OnUnequip;Qué? I guess I just clear out old data?
	sgtm 1; Reset Time to whatever it was
		
	Player.SetActorValue SpeedMult BaseSpeedMult;Reset old multiplier
		
	Set Math To (-1 * (Player.GetActorValue UnarmedDamage - MeleeDmgMult));Remove extra damage
	Player.ModActorValue UnarmedDamage Math;Reset old melee dmg
		
;Remove IMOD
	rimod RIPRageFX
	Set Active To 0

;Clear stored data
	Set BaseMeleeDmg To 0
	Set BaseSpeedMult To 0
	Set Math To 0
End


#7
gsmanners

gsmanners

    Faithful poster

  • Members
  • PipPipPipPip
  • 2,333 posts
Thanks for clarification, Cipscis.

Aren't all those SetActorValues still going to be problematic? For temporary changes like that, you really should use ModActorValue.

#8
RipperV

RipperV

    Regular

  • Members
  • PipPip
  • 70 posts
Nope, ModAV only adds on an amount, right? SetActorValue should set a definite amount, which should let me multiply the stat, like speed x 4 instead of speed + 4. For melee damage on the other hand, I'll use it; just add 20 pts and be done with it. Thanks :)

Edit: Ok, I added ModActorValue for the MeleeDamage. I think I'll keep SetActorValue for SpeedMult, since it's not effected by any specific perks, and I want to multiply it.

#9
cmal

cmal

    Enthusiast

  • Members
  • PipPip
  • 161 posts
Now that Cipcis is here, you won't be needing my help anymore with scripting.

SpeedMult and Unarmed Damage (the amount of damage you'll do Unarmed as opposed to the Unarmed Skill) both have Base Effect entries in the GECK. Since you're using constants, you could try creating an enchant that is added/removed on the player with AddSpell. That way, you won't have to do all that math and fudging with ActorValues every time your script runs. Not sure how the SpeedMult works with enchants since I always do that in scripts, but it might be worth a try. When you decide to put HP regen back in, you can make a scripted effect and just add that to your enchant -- that's sort of how the Solar Powered Perk works and I did something similar for one of my mods.

#10
RipperV

RipperV

    Regular

  • Members
  • PipPip
  • 70 posts
K, thanks for the help :) Figured out that I need to change the SpeedMult before I draw/holster, as opposed to when I draw/holster. Then I just need to find out how to make falling faster...




Page loaded in: 1.737 seconds