Keeping track of mined ore Hook into tutorial quests

Post » Wed Jun 20, 2012 1:12 pm

Hi there,

and again a question:
I've created a small mod (see signature) that provides a spell to mark an undepleted ore vein of any type in the player's vicinity. Now I have added similar spells that will mark only ore veins of a specific type (e.g. 'Find Malachite').

I thought it would be nice (instead of scattering spell tomes in the game world) to give a specialized sniffer spell whenever the player (already in possession of the generalized spell) mines a new type of ore, like an experience bonus.

So I need a method to register when a piece of ore is added to the player's inventory due to mining (not buying). In order to stay compatible with other mods I would very much prefer, not to change the MineOre(Furniture)Script.
Any idea on this?

As a second topic it would be nice to give the spells 'Harvest Flora' (also in the mod) and 'Find Any Ore' to the player when he does the introductory alchemy/smithing quests ('do you need help...').
I imagine, I could put something like
if (TutorialBlacksmithing.IsCompleted() )
into a run-once quest?

Thanks, again!
User avatar
Nick Pryce
 
Posts: 3386
Joined: Sat Jul 14, 2007 8:36 pm

Post » Thu Jun 21, 2012 3:00 am

You could try using RegisterForAnimationEvent to see when the player starts/stops mining. Then you could check for what type of ore gets added to the player. Example:

Spoiler
Int GoldOreCountInt SilverOreCount; etc.Bool PlayerHasAllSpellsEvent OnInit()    RegisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeExit")    RegisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeFloorExit")    RegisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeTableExit")    RegisterForSingleUpdate(3)EndEventEvent OnUpdate()    GoldOreCount = Game.GetPlayer().GetItemCount(GoldOre)    SilveOreCount = Game.GetPlayer().GetItemCount(SilverOre)    ;etc.    if (PlayerHasAllSpells)        UnregisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeExit")        UnregisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeFloorExit")        UnregisterForAnimationEvent(Game.GetPlayer(), "IdlePickaxeTableExit")    else        RegisterForSingleUpdate(3)    endifEndEventEvent OnAnimationEvent(ObjectReference akSource, string asEventName)    if (GoldOreCount < Game.GetPlayer().GetItemCount(GoldOre))        Player.AddSpell(FindGoldVein)    endif    if (SilverOreCount < Game.GetPlayer().GetItemCount(SilverOre))        Player.AddSpell(FindGoldVein)    endif    ;etc.EndEvent

But that's only if the player activates the ore vein instead of just attacking it. If you want to catch that too, I think the only way is to add a script to the ore veins to catch the OnHit event. You don't have to change the MineOreScript, since an object can hold more than a single script and they all receive the same events.

If you don't want to add a script to the ore veins either, then I think you're going to need to use reference aliases to dynamically attach scripts to the nearest ore veins.

Your second question seems like it should work. But you will need to put that check inside an OnUpdate() event.
User avatar
Mario Alcantar
 
Posts: 3416
Joined: Sat Aug 18, 2007 8:26 am

Post » Wed Jun 20, 2012 6:24 pm

That code looks very promising, did I mention you're a godsend?

I tested the hook into the alchemy tutorial quest, IsCompleted did not trigger anything (and would have been the wrong choice, anyway because a quest can be completed unsuccessfully, in this case by leaving the shop). But
if ( TutorialAlchemy.IsObjectiveCompleted(10) )
does the trick.
User avatar
Alister Scott
 
Posts: 3441
Joined: Sun Jul 29, 2007 2:56 am

Post » Thu Jun 21, 2012 12:03 am

Feedback: it works as you proposed with one exception:
I had to register to the 4th AnimationEvent referenced in the OreMining script: IdleFurnitureExit. The other 3 you cited didn't fire with the ore veins I tested. I kept them anyway, in case there are some veins that behave differently.

Thanks yet again!

In case someone is interested:
Spoiler
Scriptname EK_GiveIndividualOreSpells extends QuestSpell Property EK_FindOreVeinAllSpell		 AutoSpell Property EK_FindOreVeinCorundumSpell	AutoSpell Property EK_FindOreVeinEbonySpell	   AutoSpell Property EK_FindOreVeinGoldSpell		AutoSpell Property EK_FindOreVeinIronSpell		AutoSpell Property EK_FindOreVeinMalachiteSpell   AutoSpell Property EK_FindOreVeinMoonstoneSpell   AutoSpell Property EK_FindOreVeinOrichalkumSpell  AutoSpell Property EK_FindOreVeinQuicksilverSpell AutoSpell Property EK_FindOreVeinSilverSpell	  AutoGlobalVariable Property EK_GlobDisableOreExperience AutoMiscObject Property OreCorundum	AutoMiscObject Property OreEbony	   AutoMiscObject Property OreGold		AutoMiscObject Property OreIron		AutoMiscObject Property OreMalachite   AutoMiscObject Property OreMoonstone   AutoMiscObject Property OreOrichalcum  AutoMiscObject Property OreQuicksilver AutoMiscObject Property OreSilver	  Autoint IsRegistered	= 0int GaveCorundum	= 0int GaveEbony	   = 0int GaveGold		= 0int GaveIron		= 0int GaveMalachite   = 0int GaveMoonstone   = 0int GaveOrichalkum  = 0int GaveQuicksilver = 0int GaveSilver	  = 0int SpellsGiven	 = 0int CorundumOreCountint EbonyOreCountint GoldOreCountint IronOreCountint MalachiteOreCountint MoonstoneOreCountint OrichalkumOreCountint QuicksilverOreCountint SilverOreCount; run once when the script is initializedEvent OnInit()  ;Debug.Notification("Empty - OnInit")  RegisterForSingleUpdate(10.0)  GotoState("Idle")  IsRegistered = 0EndEventState Idle  Event OnUpdate()	;Debug.Notification("Idle - OnUpdate")	RegisterForSingleUpdate(10.0)	  Actor Player = Game.GetPlayer()	; advance state, if the player has the general mining spell	if ( Player.HasSpell(EK_FindOreVeinAllSpell) )	  ;Debug.Notification("advancing to state polling")	  GotoState("Polling")	  return	endif  EndEventEndStateState Polling  Event OnUpdate()	;Debug.Notification("Polling - OnUpdate")	RegisterForSingleUpdate(10.0)	; early return if quest is suspended	int DisableOreExperience = EK_GlobDisableOreExperience.GetValue() as int	if ( DisableOreExperience == 1 )	  return	endif	  Actor Player = Game.GetPlayer()	; register for animation	if ( IsRegistered == 0 )	  ;Debug.Notification("Polling - Register")	  IsRegistered = 1	  if ( !RegisterForAnimationEvent(Player, "IdleFurnitureExit") )		Debug.Notification("Failed to register for IdleFurnitureExit")	  endif	  if ( !RegisterForAnimationEvent(Player, "IdlePickaxeExit") )		Debug.Notification("Failed to register for IdlePickaxeExit")	  endif	  if ( !RegisterForAnimationEvent(Player, "IdlePickaxeFloorExit") )		Debug.Notification("Failed to register for IdlePickaxeFloorExit")	  endif	  if ( !RegisterForAnimationEvent(Player, "IdlePickaxeTableExit") )		Debug.Notification("Failed to register for IdlePickaxeTableExit")	  endif	endif	; test if the player already has the spells	if ( Player.HasSpell(EK_FindOreVeinCorundumSpell) )	  ;Debug.Notification("FindOreVeinCorundumSpell already present")	  GaveCorundum = 1	endif	if ( Player.HasSpell(EK_FindOreVeinEbonySpell) )	  ;Debug.Notification("FindOreVeinEbonySpell already present")	  GaveEbony = 1	endif	if ( Player.HasSpell(EK_FindOreVeinGoldSpell) )	  ;Debug.Notification("FindOreVeinGoldSpell already present")	  GaveGold = 1	endif	if ( Player.HasSpell(EK_FindOreVeinIronSpell) )	  ;Debug.Notification("FindOreVeinIronSpell already present")	  GaveIron = 1	endif	if ( Player.HasSpell(EK_FindOreVeinMalachiteSpell) )	  ;Debug.Notification("FindOreVeinMalachiteSpell already present")	  GaveMalachite = 1	endif	if ( Player.HasSpell(EK_FindOreVeinMoonstoneSpell) )	  ;Debug.Notification("FindOreVeinMoonstoneSpell already present")	  GaveMoonstone = 1	endif	if ( Player.HasSpell(EK_FindOreVeinOrichalkumSpell) )	  ;Debug.Notification("FindOreVeinOrichalkumSpell already present")	  GaveOrichalkum = 1	endif	if ( Player.HasSpell(EK_FindOreVeinQuicksilverSpell) )	  ;Debug.Notification("FindOreVeinQuicksilverSpell already present")	  GaveQuicksilver = 1	endif	if ( Player.HasSpell(EK_FindOreVeinSilverSpell) )	  ;Debug.Notification("FindOreVeinSilverSpell already present")	  GaveSilver = 1	endif	; stop quest when all work is done	SpellsGiven = GaveCorundum   + GaveEbony	   + GaveGold + \				  GaveIron	   + GaveMalachite   + GaveMoonstone + \				  GaveOrichalkum + GaveQuicksilver + GaveSilver	if (  SpellsGiven == 9 )	  ;Debug.Notification("Stopping Quest")	  UnregisterForAnimationEvent(Player, "IdleFurnitureExit")	  UnregisterForAnimationEvent(Player, "IdlePickaxeExit")	  UnregisterForAnimationEvent(Player, "IdlePickaxeFloorExit")	  UnregisterForAnimationEvent(Player, "IdlePickaxeTableExit")	  Stop()	  return	endif  	; store actual inventory ore count to compare against mining, later	CorundumOreCount	= Player.GetItemCount(OreCorundum)	EbonyOreCount	   = Player.GetItemCount(OreEbony)	GoldOreCount		= Player.GetItemCount(OreGold)	IronOreCount		= Player.GetItemCount(OreIron)	MalachiteOreCount   = Player.GetItemCount(OreMalachite)	MoonstoneOreCount   = Player.GetItemCount(OreMoonstone)	OrichalkumOreCount  = Player.GetItemCount(OreOrichalcum)	QuickSilverOreCount = Player.GetItemCount(OreQuickSilver)	SilverOreCount	  = Player.GetItemCount(OreSilver)  EndEvent  Event OnAnimationEvent(ObjectReference akSource, string asEventName)  ; on leaving the mining animation the player ore count will be higher	;Debug.Notification("Polling - OnAnimationEvent" + asEventName)	; early return if quest is suspended	int DisableOreExperience = EK_GlobDisableOreExperience.GetValue() as int	if ( DisableOreExperience == 1 )	  return	endif	  Actor Player = Game.GetPlayer()		if ( GaveCorundum == 0 )	  if ( CorundumOreCount < Player.GetItemCount(OreCorundum) )		Player.AddSpell(EK_FindOreVeinCorundumSpell)		return	  endif	endif	if ( GaveEbony == 0 )	  if ( EbonyOreCount < Player.GetItemCount(OreEbony) )		Player.AddSpell(EK_FindOreVeinEbonySpell)		return	  endif	endif	if ( GaveGold == 0 )	  if ( GoldOreCount < Player.GetItemCount(OreGold) )		Player.AddSpell(EK_FindOreVeinGoldSpell)		return	  endif	endif	if ( GaveIron == 0 )	  if ( IronOreCount < Player.GetItemCount(OreIron) )		Player.AddSpell(EK_FindOreVeinIronSpell)		return	  endif	endif	if ( GaveMalachite == 0 )	  if ( MalachiteOreCount < Player.GetItemCount(OreMalachite) )		Player.AddSpell(EK_FindOreVeinMalachiteSpell)		return	  endif	endif	if ( GaveMoonstone == 0 )	  if ( MoonstoneOreCount < Player.GetItemCount(OreMoonstone) )		Player.AddSpell(EK_FindOreVeinMoonstoneSpell)		return	  endif	endif	if ( GaveOrichalkum == 0 )	  if ( OrichalkumOreCount < Player.GetItemCount(OreOrichalcum) )		Player.AddSpell(EK_FindOreVeinOrichalkumSpell)		return	  endif	endif	if ( GaveQuicksilver == 0 )	  if ( QuicksilverOreCount < Player.GetItemCount(OreQuicksilver) )		Player.AddSpell(EK_FindOreVeinQuicksilverSpell)		return	  endif	endif	if ( GaveSilver == 0 )	  if ( SilverOreCount < Player.GetItemCount(OreSilver) )		Player.AddSpell(EK_FindOreVeinSilverSpell)		return	  endif	endif  EndEventEndState
User avatar
Josephine Gowing
 
Posts: 3545
Joined: Fri Jun 30, 2006 12:41 pm


Return to V - Skyrim