Jump to content

DOWNLOAD MODS

Are you looking for something shiny for your load order? We have many exclusive mods and resources you won't find anywhere else. Start your search now...

LEARN MODDING

Ready to try your hand at making your own mod creations? Visit the Enclave, the original ES/FO modding school, and learn the tricks of the trade from veteran modders...

JOIN THE ALLIANCE

Membership is free and registering unlocks image galleries, project hosting, live chat, unlimited downloads, & more...

OBSE 18, new functions, arrays & co.


ulrim
 Share

Recommended Posts

I'm building an area of effect spell with a script to catch references near the player.

This is for the horse mod I am making, so lets talk about something concrete.

The quest I am building is for commanding player owned horses.

When activated by some key, the quest should search for horse references and open a menu.

In the menu, the player may choose what horse to command.

I am investigating how to store the references in an array so the menu could be built. A while loop builds the buttons. Each button represents the selection of the reference found.

It might get more difficult with the menu part but I can handle that.

For now, however, I just want to start to know how should I build the array.

Edit: Found "Ref Walking Functions" in the obse page. I'll post my code later.

Edited by ulrim
Link to comment
Share on other sites

Well... best way to start is with a code suggestion. Then if anything's unclear, ask me what it does. :cookie:


array_var horses

ref thing


begin ScriptEffectStart

  let horses := ar_Construct Array

  let thing := GetFirstRef 36 2  ; Begin scanning creatures within a 2-cell radius

  while (thing)  ; Continue until thing == 0

    if (GetCreatureType thing == 4)  ; Horse

      if (GetOwner thing == player)

        let horses[(ar_Size horses)] := thing

        ; (ar_Size horses) starts at zero and increases every time we add an entry.

        ; Conveniently, array indices also start at zero. This saves managing an index variable!

      endif

    endif

    let thing := GetNextRef  ; If there are no more creatures this returns 0

  Loop

  ;  You now have an array of all local player-owned horses.

  ;  Do something with it!

end

Link to comment
Share on other sites

Ok. Like I promised, now that I got to play with it I managed to get what I wanted.

Just need some help figuring out if this can be optimized or if there's something that should be better.

XD ) array_var horses ref thing array_var horse short init short finding short found short key short queue ref horseRef short menu short button begin GameMode if fQuestDelayTime == 0 let fQuestDelaytime := 0.001 endif if init let horses := ar_Construct Array let thing := GetFirstRef 36 2 ; Begin scanning creatures within a 25-cell radius (depths: 1 scans 8 cells, 2 scans 25 cells) while (thing) ; Continue until thing == 0 if (GetCreatureType thing == 4) ; Horse if (GetOwner thing == player) if (thing.GetDead == 0) let horses[(ar_Size horses)] := thing ; (ar_Size horses) starts at zero and increases every time we add an entry. ; Conveniently, array indices also start at zero. This saves managing an index variable! endif endif endif let thing := GetNextRef ; If there are no more creatures this returns 0 Loop ; You now have an array of all local player-owned horses. ; Do something with it! let found := (ar_Size horses) if found > 0 let finding := 1 else SetMessageIcon "icons\uh_icon.dds" MessageEx "I have no horses." endif let init := 0 endif if finding ForEach horse <- horses if menu == 0 let key := horse["key"] if key == queue ; queue starts at zero ;let queue := queue + 1 ; menu handles queue. let horseRef := horse["value"] let menu := 1 endif endif loop let finding := 0 endif if menu ; only starts if there is at least one horse if found == 1 let menu := 0 ;let uchMenuQ.pcHorseRef := horseRef ;let uhcMenuQ.menu := 1 ;StartQuest uchMenuQ ;StopQuest uhcFindQ return endif if menu == 1 ; which horse to select? 2 if queue > found let queue := 0 ; reached end of array. cycle from begining.. else let queue := (queue + 1) ; since queue starts at zero, key zero = horse one endif MessageBoxEX "There are %.0f horses near me. %r Horse %.0f of %.0f is %n. %r Command this horse? %r ========================================= %r | Yes | No | Cancel " found queue found horseRef let menu := -1 let button := -1 elseif menu == -1 let button := GetButtonPressed endif endif end begin MenuMode if button == 0 ; Yes let queue := 0 let menu := 0 ;let uchMenuQ.pcHorseRef := horseRef ;let uhcMenuQ.menu := 1 ;StartQuest uchMenuQ ;StopQuest uhcFindQ return elseif button == 1 ; No, cycle to next horse. let finding := 1 elseif button == 2 ; Cancel let queue := 0 let menu := 0 ;StopQuest uhcFindQ endif end
; 2010/05/19: created by ulrim

;------------------------------------------------------------------

; Info: service, finds horses

;

; Related: uhcFindQ (quest)

;------------------------------------------------------------------

scn uhcFindQscr


float fQuestDelayTime


; find horse variables for the while loop suggested by Tejón (thanks mate 

Edited by ulrim
Link to comment
Share on other sites

I'd appreciate if someone could enlighten me a bit on array keys and ar_HasKey.

What I intend to do is to get a value from a StringMap array that matches the key given.

I am using a reference var that holds the key, like so:

if (ar_HasKey some_array horseRef)
ar_HasKey - returns true if the array has an element with the specified key

(hasKey:bool) ar_HasKey src:array key:arrayKey

Link to comment
Share on other sites

Update with the script.

I've let this message on beth, hope you don't mind me posting here too.

I've been trying to associate two objects by array with little success. Maybe one of you could help.

Is it a good idea to use string map arrays to associate references? Feel free to discuss your opinion, too.

The idea is to mark some location with a marker reference. An AI package tracks the reference, affecting behavior of a creature.

For each creature that the mod changes, give it a unique marker. (One marker for each creature.)

Basic idea:

ref creature		 ; some selected creature by external script

ref markerRef		; marker the AI package targets


array_var markers	; the association between creatures and markers!

array_var item


short newMarker


if eval !(markers)					   ; array not initialised before

  let markers := ar_Construct StringMap

endif


ForEach item <- markers				  ; check if this creature has a marker already associated

  if eval creature := item["key"]

	let markerRef := item["value"]	   ; already has one, get marker

  else

	let newMarker := 1				   ; doesn't have one, lets give the creature a new marker

  endif

loop


if newMarker

  let markerRef := CloneForm xMarkerRef  ; xMarkerRef is the one created in the CS Editor

  let markers[creature] := markerRef	 ; associate the creature with the marker

  let newMarker := 0

endif


; do stuff with marker

markerRef.MoveTo player


; update creature AI

if eval !(creature.GetIsCurrentPackage somePkgWithMarker)

  creature.AddScriptPackage somePkgWithMarker

  creature.EvaluatePackage

endif
This doesn't work. The error goes like: "Invalid operands for operator [." To make it work you have to do like this:
let markers[$(creature)] := markerRef

The problem is, when calling toString (or the "$" sign) on a reference, it takes the object name if it has one. However, different objects may have the same name.

I just want to associate two objects by taking their references.

It is meant to pass the object ID (or ref) to the StringMap array and check if there is one. If $(creature) passes a string with the name instead of the ID, then it's not good.

What do you propose?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...