Help with OnHit script

Post » Mon Nov 19, 2012 11:09 pm

I'm working on a sequence in my quest where the player goes to a prison to negotiate the release of a prisoner. If they pass the challenges, they can do it peacefully, however, if they fail the challenges, all the bad guys in the prison become hostile and you have to fight your way to the objective. I have all of this set up via dialog and setting the appropriate quest stage for the pass or fail scenarios. If the player fails, I set all of the bad guys relationship to the player as enemy so they attack on sight like this:

Alias_ThalmorGuard01.GetActorRef().SetRelationshipRank(Game.GetPlayer(), -4)

But one thing I need to account for is what if the player decides they just want to fight and start attacking - even if they have passed the challenges and negotiated a peaceful release? If this happened, I want ALL the bad guys to immediately become hostile to the player, and attack. I'm not sure, but wouldn't I need to use an OnHit script placed on each of my bad guys? If so, here's what I have come up with so far:

Scriptname BalokOnHitSetStage extends Actorimport gameimport debugQuest Property MyQuest autoInt Property stage  Autoauto State waiting	Event onHit(objectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)		MyQuest.SetCurrentStageID(stage)		gotoState ("allDone")	endEventendStateState allDone	;do nothingendState 

This compiles, but I don't think it is right. I picked up bits of this from another default OnHit script to get this far.

Basically, if I wrote it in English, I think I need to do this:

"If the player hits the bad guy, set my stage to 63. If stage 63 has already been set, then do nothing because they should already be set to hostile anyway."

Also, could I set their hostility via a quest variable of some type or something? Would that be a cleaner way to do it? I don't know much about setting up and using quest variables to control stuff, so you might have to walk me through it if so.

One last thing, most of these bad guys are just generic "Thalmor Soldiers" that I've created. I will be returning to the prison at a later stage in my main quest, so I want to be able to respawn them and use them again since they are generic. The second time to the prison, they should be completely hostile from the beginning which I should be able to set like I did with this:
Alias_ThalmorGuard01.GetActorRef().SetRelationshipRank(Game.GetPlayer(), -4)
User avatar
Rebekah Rebekah Nicole
 
Posts: 3477
Joined: Fri Oct 13, 2006 8:47 pm

Post » Tue Nov 20, 2012 4:47 am

I think you need to check if the player is the aggressor then check what stage your quest is at. Try this modification of your code:

Spoiler
Scriptname BalokOnHitSetStage extends Actorimport gameimport debugQuest Property MyQuest autoObjectReference Property PlayerRef autoInt Property stage  Autoauto State waiting	    Event onHit(objectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)			    if akAggressor==PlayerRef && MyQuest.GetCurrentStageID()<63				   MyQuest.SetCurrentStageID(stage)				   gotoState ("allDone")			    endIf	    endEventendStateState allDone	    ;do nothingendState
User avatar
Markie Mark
 
Posts: 3420
Joined: Tue Dec 04, 2007 7:24 am

Post » Tue Nov 20, 2012 12:14 am

Hey Zartar (or anybody else who wants to chime in), thanks for the reply, and I apologize that I haven't responded until now. As these things go sometimes, feature creep has set in on this portion of my quest, and this simple script is going to have to be a little more complex, lol. (That, or maybe I just need to add another script to my NPC's?)

I'll try to detail what I'm trying to accomplish as succinctly as I can, and perhaps you and the other gurus can help me sort this out.

The first objective is to go to the prison and free the prisoner (Korst) from captivity, with an Optional objective to negotiate a peaceful release of him. If the player fails the optional objective I have a stage set that makes all the bad guys hostile upon that failure, and the fight ensues. I need to display an objective with either a countdown of how many bad guys are left, or pointers on each of them so you will know you are done when there are no more pointers or the countdown reaches zero. This should update the objective to go find Korst.

If the player fails the challenge or chooses another dialog option, they will likewise fail, and set the combat stage mentioned above.

If they pass the challenge, they will get escorted to the holding cell to get Korst. However, after a scene with the Thalmor torturer and a Justiciar, the torturer disobeys his superior and attacks the player anyway, lol. So at this point I need to display the objective to kill all the bad guys in the prison.

I think it might be best to put the script on the quest alias rather than the base NPC, because I will be using the guards again later on. I will probably do that in another quest, so I can set aliases again in that quest.

Hopefully, this will make sense, lol.
User avatar
Rachel Eloise Getoutofmyface
 
Posts: 3445
Joined: Mon Oct 09, 2006 5:20 pm

Post » Mon Nov 19, 2012 8:21 pm

See if this looks right to you guys:

Spoiler
Scriptname BalokThalmorGuardsScript extends Actorimport gameimport debugQuest Property BalokThalmorPrisonQuest autoQuest Property BalokHelgen01 autoObjectReference Property PlayerRef autoGlobalVariable Property BalokThalmorGuardCount  Auto  auto State waiting    Event onHit(objectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)	    if akAggressor==PlayerRef && BalokThalmorPrisonQuest.GetCurrentStageID()<50			 BalokThalmorPrisonQuest.SetCurrentStageID(50)		 endIf    endEvent    Event OnDeath(Actor akKiller)	 BalokThalmorGuardCount.Value -= 1		 If (BalokThalmorGuardCount.Value < 1) && BalokThalmorPrisonQuest.GetCurrentStageID() == 50		 BalokThalmorPrisonQuest.SetCurrentStageID(60)		 ElseIf (BalokThalmorGuardCount.Value < 1) && BalokThalmorPrisonQuest.GetCurrentStageID() == 90		 BalokHelgen01.SetCurrentStageID(100)		 gotoState ("allDone")	 endifendEventendStateState allDone	 ;do nothingendState
User avatar
ONLY ME!!!!
 
Posts: 3479
Joined: Tue Aug 28, 2007 12:16 pm

Post » Mon Nov 19, 2012 9:25 pm

Well, I plugged that in and it fails:

" function ondeath cannot be defined in state waiting without also being defined in the empty state"

any suggestions?
User avatar
Jinx Sykes
 
Posts: 3501
Joined: Sat Jan 20, 2007 11:12 pm

Post » Tue Nov 20, 2012 9:40 am


That looks fine to me though without knowing what the quest stages mean I cannot know for sure. One small thing I can point out is if the script is attached to the alias and your Thalmor actors are in that alias, you don't need one of your quest property's. You can use GetOwningQuest() instead since the alias is owned by the quest. For example: GetOwningQuest().SetCurrentStageID(60)

Try it again without the states (since the states are just used to stop further OnHit() events from being recieved after the actor is dead).
User avatar
Ben sutton
 
Posts: 3427
Joined: Sun Jun 10, 2007 4:01 am

Post » Mon Nov 19, 2012 9:01 pm

Thanks Zartar, I made those edits to the states and added my first guard alias and it compiled just fine. One question though, wouldn't I need to change it to extend ReferenceAlias instead of Actor or does that matter?

I just left the properties for my quests as its easier for me to read and they auto fill so it don't take any time really. I'm pretty sure the stages are correct as I have it charted out on a spreadsheet. I'm pooped right now and have a long day tomorrow. My day gig REALLY cuts into my modding time, lol. But hopefully in the next day or two, I'll get all my packages, scenes and what not worked out and test this all out. I have most of it in place and just need to work out all the conditions for the packages based on the stages, and plug in a little more test dialog in the scenes, and it will be ready. Thanks again for your help!
User avatar
Guinevere Wood
 
Posts: 3368
Joined: Mon Dec 04, 2006 3:06 pm

Post » Tue Nov 20, 2012 3:37 am

Thanks Zartar, I made those edits to the states and added my first guard alias and it compiled just fine. One question though, wouldn't I need to change it to extend ReferenceAlias instead of Actor or does that matter?

Yes, it should extend ReferenceAlias. Remember to fix the dialogue bug before you start testing. Good luck!
User avatar
Kat Ives
 
Posts: 3408
Joined: Tue Aug 28, 2007 2:11 pm

Post » Mon Nov 19, 2012 10:44 pm

Spoiler
Scriptname BalokThalmorGuardsScript extends ReferenceAliasimport gameimport debugQuest Property BalokThalmorPrisonQuest autoQuest Property BalokHelgen01 autoObjectReference Property PlayerRef autoGlobalVariable Property BalokThalmorGuardCount  Auto auto State waiting    Event onHit(objectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)		    if akAggressor==PlayerRef && BalokThalmorPrisonQuest.GetCurrentStageID()<50						 GoToState("KillThalmor")						 BalokThalmorPrisonQuest.SetCurrentStageID(50)				 endIf    endEventEndStateState KillThalmorEvent OnDeath(Actor akKiller)		 BalokThalmorGuardCount.Value -= 1				 If (BalokThalmorGuardCount.Value < 1) && BalokThalmorPrisonQuest.GetCurrentStageID() == 50				 BalokThalmorPrisonQuest.SetCurrentStageID(60)				 ElseIf (BalokThalmorGuardCount.Value < 1) && BalokThalmorPrisonQuest.GetCurrentStageID() == 90				 BalokHelgen01.SetCurrentStageID(100)				 gotoState ("allDone")		 endifendEventEndStateState allDone		 ;do nothingendState

BTW if you want to use states (which is advisable) try this code.
User avatar
how solid
 
Posts: 3434
Joined: Mon Apr 23, 2007 5:27 am

Post » Tue Nov 20, 2012 7:58 am

Thanks again Zartar, I'll plug that in when I get home. Just one final question on the states. If I'm reading that correctly, when the state is set to allDone, it essentially checks out that script and it does nothing at all from there on out? Is that correct? The reason I ask is that I'll probably be doing something similar the 2nd time around to the prison, but they will be on new aliases.

Thanks again! (This is a HUGE hurdle for me in my main quest and was key in my moving forward to the next parts!)
User avatar
James Smart
 
Posts: 3362
Joined: Sun Nov 04, 2007 7:49 pm

Post » Mon Nov 19, 2012 7:51 pm

Yes, when the script's state is set to done it will not listen for any events. You could also clear the alias instead of going to the state all done but either way is fine.

In this case, the states are useful for optimizing your code since the OnHit() event will only fire once on the actor and then your script will listen for the OnDeath() event to fire once before stopping (without states the OnHit() event will fire every time you hit the actor even if the actor is dead!). If your are using a similar script on different aliases there will be no problems.
User avatar
saxon
 
Posts: 3376
Joined: Wed Sep 19, 2007 2:45 am

Post » Mon Nov 19, 2012 10:14 pm

Well, I'm back and have this all plugged in now and am starting to test. Unfortunately, my countdown ain't working, lol. I'm pretty sure the problem is with the states in the script. Here's the script that will not run my global count, followed by a shortened script that works as it should.

Spoiler

Scriptname BalokThalmorGuardsScript extends ReferenceAliasimport gameimport debugQuest Property BalokThalmorPrison autoObjectReference Property PlayerRef autoGlobalVariable Property BalokThalmorGuardCount  Auto  auto State waiting	Event onHit(objectReference akAggressor, Form akWeapon, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)		 if akAggressor==PlayerRef && BalokThalmorPrison.GetCurrentStageID()&--#60;50			 GoToState("KillThalmor")			 BalokThalmorPrison.SetCurrentStageID(50)			 Debug.Notification("player started a fight stage 50 set")		endIf	endEventEndStateState KillThalmorEvent OnDeath(Actor akKiller)	 BalokThalmorGuardCount.Value -= 1	 Debug.Notification("global count minus 1")   If (BalokThalmorGuardCount.Value &--#60; 1) && BalokThalmorPrison.GetCurrentStageID() == 50		 BalokThalmorPrison.SetCurrentStageID(60)		 Debug.Notification("global count is done stage 60 set")		 ElseIf (BalokThalmorGuardCount.Value &--#60; 1) && BalokThalmorPrison.GetCurrentStageID() == 90		 BalokThalmorPrison.SetCurrentStageID(100)		 Debug.Notification("global count is done stage 100 set")		 gotoState ("allDone")	endifendEventEndStateState allDone	 ;do nothingendState
^ not counting down on death


Spoiler
Scriptname BalokThalmorGuardsScript extends ReferenceAliasimport gameimport debugQuest Property BalokThalmorPrison autoObjectReference Property PlayerRef autoGlobalVariable Property BalokThalmorGuardCount  Auto  auto State waitingEvent OnDeath(Actor akKiller)	 BalokThalmorGuardCount.Value -= 1	 Debug.Notification("global count minus 1")	If (BalokThalmorGuardCount.Value &--#60; 1) && BalokThalmorPrison.GetCurrentStageID() == 50		 BalokThalmorPrison.SetCurrentStageID(60)		 Debug.Notification("global count is done stage 60 set")		 ElseIf (BalokThalmorGuardCount.Value &--#60; 1) && BalokThalmorPrison.GetCurrentStageID() == 90		 BalokThalmorPrison.SetCurrentStageID(100)		 Debug.Notification("global count is done stage 100 set")		 gotoState ("allDone")	endifendEventEndStateState allDone	 ;do nothingendState
^ counting as it should. All I did was remove that first state block.

I put the debug notices in just so I could find the trouble spots. Any suggestions?
User avatar
Angus Poole
 
Posts: 3594
Joined: Fri Aug 03, 2007 9:04 pm

Post » Tue Nov 20, 2012 2:59 am

OK I think I figured it out. The GoToState("KillThalmor") was not firing because it was in the if block. Since the player was not the aggressor in my tests it was never setting the state to killthalmor therefore my count was not running. I moved the gotostate above the if block and it runs fine on initial tests. Now I got to figure out how to get my global count to show in my quest objective.
User avatar
Liv Staff
 
Posts: 3473
Joined: Wed Oct 25, 2006 10:51 pm


Return to V - Skyrim