ReDragon2013 Posted April 1, 2021 Share Posted April 1, 2021 (edited) subhuman0100 wrote: "the tone of your post seems to be that you're disagreeing with me"I am sorry. I would not make you angry or flaming your post.8-bit digit, from 0 .. 255-------------------------------hexadecimal 0x00 .. 0xffbinary 0000 0000 .. 1111 111110-bit digit, from 0 .. 1023----------------------------------hexadecimal 0x000 .. 0x3ffbinary 00 0000 0000 .. 11 1111 111132-bit digit unsigned, our papyrus "int" type------------------------------------------------------hexadecimal 0x00000000 .. 0xffffffffdecimal 0 .. 4,294,967,295 bit31 bit23 bit15 bit7 bit0 | | | | | binary 00000000 00000000 00000000 00000000 .. each bit can be unset 11111111 11111111 11111111 11111111 or set(1) re-order of 32 bits for better explanation bits 10 9 8 7 6 5 4 3 2 1 0 / / / / / / / / / / / | | | | | | | | | | | binary 0 0 0 0 0 0 0 0 0 0 0 10 bits + unused bit10 ---------------------------------------------- bits 21 20 19 18 17 16 15 14 13 12 11 / / / / / / / / / / / | | | | | | | | | | | binary 0 0 0 0 0 0 0 0 0 0 0 10 bits + unused bit21 --------------------------------------------- bits 31 30 29 28 27 26 25 24 23 22 / / / / / / / / / / | | | | | | | | | | binary 0 0 0 0 0 0 0 0 0 0 10 bits left(2) code to "compress" as follow: int i = 0x00000000 ; init by Zero; our three 10-bit digits, with different values as sample int n1 = 0x1ff ; 511 int n2 = 0x2ff ; 767 int n3 = 0x3ff ; 1023; store n1 into i i = n1 ; that is simple; fill bits 11 up to 20 i = i + (n2 * 0x800) ; hex 0x800, dec 2048; fill bits 22 up to 31 i = i + (n3 * 0x400000) ; explanation with binaries for variable "i" ; 00000000 00 | 0 | 00000 00000 | 0 | 00 00000000 = 0x00 ; -------------------------------------------------------------- ; 01 11111111 = i1 = 0x1ff ; 10111 11111 = i2 = 0x2ff ; 11111111 11 = i3 = 0x3ff ; ------------------------------------------------ ; 11111111 11 0 10111 11111 0 01 11111111 = i = 0xffd7f9ff(3) and now the "decompress" code: Keep in mind: bit10 and bit21 are unused!you wrote: "But I'm not sure where you're going with the modulus. Could you explain that?"; get back the 10-bit digits n3 = i / 0x400000 ; div n1 = i % 0x800 ; modulo by 2048;all in one n2 = ((i % 0x400000) - (i % 0x800)) / 0x800; or step by step n2 = i % 0x400000 ; modulo by n2 = n2 - n1 ; subtract the first digit n2 = n2 / 0x800 ; div Edited April 1, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
AnishaDawn Posted April 3, 2021 Share Posted April 3, 2021 Another option is to use a form array. You can return multiple form types that way if you know what you're expecting. That won't work for returning say an Int and a CK form like Actor, but will work for CK forms.My hopes and my dreams crashed and burned into eternal nothingness. Forever shall I wonder alone weeping over this sheer travesty anywhere and everywhere within nowhere. :wallbash: Link to comment Share on other sites More sharing options...
dylbill Posted April 3, 2021 Share Posted April 3, 2021 Wow, so dramatic. You gonna be alright there? If using StorageUtil from PapyrusUtil it would make this a lot easier to do: MiscObject Property Lockpick Auto Event OnInit() Form[] MyFormArray = MyCoolFunction(Lockpick, Game.GetPlayer(), 1000) Int IntA = StorageUtil.GetIntValue(MyFormArray[0], "MyCoolMod_Int") Int IntB = StorageUtil.GetIntValue(MyFormArray[1], "MyCoolMod_Int") EndEvent Form[] Function MyCoolFunction(Form akForm, ObjectReference akCenter, Float akRadius) Form[] MyFormArray = New Form[2] MyFormArray[0] = Game.FindRandomReferenceOfTypeFromRef(akForm, akCenter, akRadius) MyFormArray[1] = Game.FindRandomActorFromRef(akCenter, akRadius) If MyFormArray[0] StorageUtil.SetIntValue(MyFormArray[0], "MyCoolMod_Int", Utility.RandomInt(0, 100)) Endif If MyFormArray[1] StorageUtil.SetIntValue(MyFormArray[1], "MyCoolMod_Int", Utility.RandomInt(0, 100)) Endif Return MyFormArray EndFunction Link to comment Share on other sites More sharing options...
AnishaDawn Posted April 4, 2021 Share Posted April 4, 2021 It was a joke lol. I do wish this game had the Var type like Fallout 4 though. Link to comment Share on other sites More sharing options...
dylbill Posted April 4, 2021 Share Posted April 4, 2021 Lol yes that would be nice. There's a lot of things that F04 has that I wish Skyrim had. That, structs and RegisterForRemoteEvent would all be nice. I guess we'll have to wait for ES6. Link to comment Share on other sites More sharing options...
subhuman0100 Posted April 4, 2021 Share Posted April 4, 2021 (edited) i = i + (n2 * 0x800) ; hex 0x800, dec 2048Yep, this I got. You're doing the same thing I did. I kinda touched on it in my earlier reply, when I said a multiplication or division by a power of 2 is a shift. We, all of us "shift" dozens or hundred of times in our daily lives, but we do it without thinking about what we're doing.If you have to figure out "89 * 100" probably nobody gets out a paper and pencil and calculates it. Any power of ten, for division or multiplication you just look at it and shift the digits over to get the answer. In this case, 100=10^2 so it's the base-10 version of a LeftShift 2, or shift the digits "89" two places to the left, and backfill with two zeroes to get "8900"It's the same in binary, if you're multiplying or dividing by a power of two, you just shift the digits and get the answer.So what you wrote as "n2 * 0x800" is shifting 11 bits, where I wrote it as shifting 10 bits "Math.LeftShift(n2, 10)" They're basicly the same thing. The only question comes down to: n2 = n2 / 0x800 ; divThat can be RightShift(n2, 11) but the difference is I don't know how well Papyrus is optimized. If you do that in GCC or Java, the compiler bytecode output will be a shift. I don't know if Papyrus will do that, and the time difference can be considerable. An x86 does well with addition, subtraction and multiplication- but comparatively, division is very slow whereas a shift is one of the most basic functions a digital device can do. It's a single clock cycle, even the room-sized early computers from 70 years ago could do a shift, the Intel 4004 from 50 years ago only had a total instruction set of 40-some instructions, and shifts were part of it. It's one of the simplest and most basic things a computer can do.Tip: this "shifting" shortcut everyone already knows applies elsewhere, not just base-10(decimal). 0xDEADBEEF * 0x100 = DEADBEEF00 So you're doing what I did, but using different instructions. Thank you for the modulus explanation!I'm gonna chalk that up to "different people think differently" because what you called simpler, I see see as the opposite. But if it helps someone else, it's good! Edited April 4, 2021 by subhuman0100 Link to comment Share on other sites More sharing options...
ReDragon2013 Posted April 5, 2021 Share Posted April 5, 2021 (edited) Conclusion: Different ways lead to the same aim. I know that a division or modulo operation is slower than Shift Right or And operation.The fact is (and that was my statement) all you do with SKSE LogicalXXX functions can be done with vanilla papyrus math operators. (1) your version (is calling 11x SKSE based Math.LogicalXXX() functions to reach the aim) ;-------------------------------------------------- Int FUNCTION compress(Int int1, Int int2, Int int3) ;-------------------------------------------------- int1 = Math.LogicalAnd(int1, 0x03FF) ; ensure it\'s not more than 10 bits in length - the above mentioned check int2 = Math.LogicalAnd(int2, 0x03FF) ; or else it will (in later steps) overflow into int3 = Math.LogicalAnd(int3, 0x03FF) ; the next int\'s space int returnInt = Math.ShiftLeft(int1, 10) ; bits 1-10 of int1 are now in position 11-20 on returnInt returnInt = Math.LogicalOr(returnInt, int2) ; the previous line is still true, but now also bits 1-10 of int2 are in returnInt\'s bits 1-10 returnInt = Math.ShiftLeft(returnInt, 10) ; now int1 is bits 21-30 of returnInt, and int2 is bits 11-20 ;;returnInt = Math.LogicanOr(returnInt, int3) ; typo here! returnInt = Math.LogicalOr(returnInt, int3) ; our send value is done, the previous line is still true, but we\'ve now stuffed int3 into positions 1-10 RETURN returnInt ENDFUNCTION ;---------------------- FUNCTION someFunction() ;---------------------- int returnedInt = compress(0x01ff, 0x02ff, 0x03ff) ; decompress now int newInt3 = Math.LogicalAnd(returnedInt, 0x03FF) ; pull out ten bits returnedInt = Math.ShiftRight(returnedInt, 10) ; shift right 10 bits int newInt2 = Math.LogicalAnd(returnedInt, 0x03FF) ; pull out next ten bits int newInt1 = Math.ShiftRight(returnedInt, 10) ; shift right ten again for yes, this is my final answer ; voila ENDFUNCTION (2) my version (has taken vanilla papyrus math operators to get the same result) https://www.creationkit.com/index.php?title=Operator_Reference Int T = 0x400000 ; dec 4194304, defined constant for better overview ;-------------------------------------------- Int FUNCTION compress(Int n1, Int n2, Int n3) ; n1 = int1 ;-------------------------------------------- RETURN (n1 + (n2 * 0x800) + (n3 * T)) ; 2x multiplication, 2x addition ENDFUNCTION ;---------------------- FUNCTION someFunction() ;---------------------- int r = compress(0x01ff, 0x02ff, 0x03ff) ; r = returnedInt ; decompress now int n3 = r / T ; n3 = newInt3 int n1 = r % 0x800 ; variant (1) int n2 = ((r % T) - (r % 0x800)) / 0x800 ; 2x division, 3x modulo, 1x substraction ; variant (2) redundant code removed int n2 = ((r % T) - n1) / 0x800 ; 2x division, 2x modulo, 1x substraction ; voila ENDFUNCTION (3) You wrote: "I'm gonna chalk that up to "different people think differently" because what you called simpler, I see see as the opposite." Maybe you do not really understand what I meant. My suggestion was next code; no overhead, no costs to compress and decompress Int int1 Int int2 Int int3 ;---------------- FUNCTION Func_1() ;---------------- int1 = 0x01ff ; store value here, no compression int2 = 0x02ff int3 = 0x03ff ENDFUNCTION ;---------------- FUNCTION Func_2() ;---------------- int i = int1 ; get back the stored value, decompression not required int j = int2 int m = int3 ENDFUNCTIONThat means normally its not required to get a "return of multiple values from a function". Edited April 5, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
PeterMartyr Posted April 5, 2021 Share Posted April 5, 2021 I was embarrassed reading this, what a pointless argument! I am sure there way more ways to return 3 lousy numbers too! lol Come on kiss and make up now, this is not that important. @subhuman return 3 something NOT raw or primitive a in method that does not return a list or your argument is pointless in my humble opinion. The Collatz Conjecture needs people like you, jump to it. Link to comment Share on other sites More sharing options...
AnishaDawn Posted April 7, 2021 Share Posted April 7, 2021 I was late the party but here's my 2 septims: Both of your routes are good there's just one difference from what I can see: 1. subhuman's route, the SKSE route, does all the math underneath. This is convenient for people not too savy at math. It's clean, quick, not head pounding.2. ReDragon2013's route, the vanilla route: I like this one because he shows the math being done - this is a great way to how you learn from others. -RAMBLING START- My math teacher would always say to appreciate the work being shown with math, and for worksheets that only allowed space for answers, she wanted us to show the work on a separate sheet -RAMBLING END-. Anyway, this is also it's a proven way to get around using a 3rd party extension. Link to comment Share on other sites More sharing options...
Recommended Posts