Always changing
#1
Posté 03 décembre 2012 - 08:51
I have in mind something for this month's CCC: Spoils, but it's something I haven't seen any discussion about, which probably means it's impossible.
There was one thread a couple years back, but all the suggestions were work-arounds and slieght of hand.
Can we change appearance of a placeable the way we can with characters (polymorph), items, heads/helmets and body-parts?
What function is being called to make the actual appearance change? Can it be adapted to work on placeables?
My idea? A pile of treasure that grows/shrinks based on the value of the items/gold it contains. Say 10 different models of coins and gems and what-not of increasing size.
Anyone ever dig into this?
<...waiting for his ship to come in>
#2
Posté 03 décembre 2012 - 09:12
#3
Posté 04 décembre 2012 - 03:05
Rose on top of a table
speakstring "Abracadabra!"
VFX_IMP_STUN effect
the rose is now a rabbit.
crowd goes wild.
The Great Hazzini takes a bow.
#4
Posté 04 décembre 2012 - 06:07
Would have been nice... :-/
Well, I've modified the idea a bit and now I'm hoping for some participation from bit-wise old scripters =)
I'll make a base container placeable that will create/destroy dependent placeables based on the value of the items it holds.
The dependent placeables will be sized in binary fashion (i.e. the #2 is twice the volume of #1, #3 is twice the volume of #2, etc. They will all have the same origin, but be offset in different directions, with overlap. In fact, the first 3 will mostly just fill up the interior of the chest (with a little spillage).
The functionality should be something like:
- Item added:Calculate total value. Scale (log?) value to 8-bits (with 9th model for overflow). Create bits that are 1. Destroy bits that are 0.
- Item removed: Calculate total value remaining. Scale... etc.
So PC walks up to this huge pile of a dragon's hoard and starts grabbing (tons!) stuff. The pile shifts and shrinks. PC can't move. Puts most back. Pile grows. PC comes back later, but his best friend beat him to it :-)
What do you think?
<...rue and tossing it in the greens bin>
Modifié par Rolo Kipp, 04 décembre 2012 - 06:09 .
#5
Posté 06 décembre 2012 - 02:02
Whoa, Who are you calling old?Rolo Kipp wrote...
<ruefully pulling up...>
Would have been nice... :-/
Well, I've modified the idea a bit and now I'm hoping for some participation from bit-wise old scripters =)
Sounds good, I myself would make it an invisiable base container placeable. The other placable would hold no inventory but be usable, Having the OnUsed event of created placeables open the inventory screen of the invisiable one.I'll make a base container placeable that will create/destroy dependent placeables based on the value of the items it holds.
The dependent placeables will be sized in binary fashion (i.e. the #2 is twice the volume of #1, #3 is twice the volume of #2, etc. They will all have the same origin, but be offset in different directions, with overlap. In fact, the first 3 will mostly just fill up the interior of the chest (with a little spillage).
Hmm, I am not sure i like the double Idea, I guess that before I could decide on that though I would need to know the size of each area you where going to try and fit the items into... Hmm on reading this a second time, are you talking about sizing the placables or just adding more?
I do not really like the Idea of calculating off of total value. One uber sword could end up making a pile bigger then 200 potions. I think the calculation should be done off of InvSlotWidth•InvSlotHeight. That way the pile will be more representive of the Size of the loot.The functionality should be something like:
• Item added:Calculate total value. Scale (log?) value to 8-bits (with 9th model for overflow). Create bits that are 1. Destroy bits that are 0.
As far as the log Question: Yes log base 2 will return the position of the largest bit set. nwscript only has a natural log so you will have to convert it from log base e to log base 2. so in nwscript logBase2(x) = log(x)/log(2)
• Item removed: Calculate total value remaining. Scale... etc.
So PC walks up to this huge pile of a dragon's hoard and starts grabbing (tons!) stuff. The pile shifts and shrinks. PC can't move. Puts most back. Pile grows. PC comes back later, but his best friend beat him to it :-)
What do you think?
<...rue and tossing it in the greens bin>
I like the Idea. I still dont like the double Idea though, Unless you are making each ring twice the area size of the one before. Or rather 3 times the size of the inner ring.
I think I would model it more after the way electrons fill an atom. where the number of electrons in each shell is 2*n*n and the and the fill is in regular pattern.
Modifié par Lightfoot8, 06 décembre 2012 - 02:05 .
#6
Posté 07 décembre 2012 - 06:17
I'll put together some stuff this weekend to try to make it clearer.
Basically, the dependent placeables are a visual indication of the value in the hoard. So a value that renders down to 37, say, would be placeable 6 (32), placeable 3 (4) and placeable 1. All three would be displayed in a overlaping but non-replacing fashion. I.e, there'd be a big pile (6), and to the side a small pile (3) and some stuff in the bottom of the chest (1).
If the hoard was maxed out, there'd be the *huge* pile (9 = overflow) and all 8 smaller piles arranged to fill a radius of about 5m (the entire hoard would be 1 tile across).
Edit: or possibly 2 tiles across. But that would require builders make sure the hoard is in a big open area...
I like the idea of the dependent placeables opening the inventory, but why use a separate invisible placeable when the base object (0) would always be rendered?
<...and trying to get visual>
Modifié par Rolo Kipp, 07 décembre 2012 - 06:18 .
#7
Posté 08 décembre 2012 - 05:31
Rolo Kipp wrote...
The dependent placeables will be sized in binary fashion (i.e. the #2 is twice the volume of #1, #3 is twice the volume of #2, etc. They will all have the same origin, but be offset in different directions, with overlap. In fact, the first 3 will mostly just fill up the interior of the chest (with a little spillage).
When you are saying #1, #2 and Number #3.
Are they bit numbers?
#1 (0010)
#2 (0100)
#3 (1000) // Yes bits are 0 based.
Or are they numbers?
#1 (0001)
#2 (0010)
#3 (0011)
Bit Numbers
If they are Bit numbers. The Scale would simply be your Total Chest Value(TCV) devided by a Scale Value(SV).
Scale = TCV/SV;
That would give you no Bits set until you reached you SV.
0 <TCV > SV = (0000) // bits
SV < TCV > 2SV = (0001)
2SV < TCV > 4SV = (001?) // ? means the value may or may not be set.
4SV < TCV > 8SV = (01??)
8SV < TCV > 16SV = (1???)
If you wanted to shift the scale up one, so that the first bit was set with the first item placed in the chest, you would just add the SV to the TCV before the division.
Scale = (TCV+SV)/ SV
Giving you:
0 <TCV > SV = (0001) // bits
SV < TCV > 2SV = (001?)
2SV < TCV > 4SV = (01??)
4SV < TCV > 8SV = (1???)
With a SV of 10,000 this would look like.
0 <TCV > 10,000 = (0001) // bits
10,000 < TCV > 20,000 = (001?)
20,000 < TCV > 40,000 = (01??)
40,000 < TCV > 80,000 = (1???)
...
64,000 <TCV> 128,000 = (1???_????) // Bit 8 Set.
Numbers
If they are numbers. It would be a log base 2.
Scale = log(TCV) / log(2)
(TCV < 2) = 0 (0000)
(TCV< 4) = 1 (0001)
(TCV< 8) = 2 (0010)
(TCV< 16) = 3 (0011)
(TCV< 32) = 4 (0100)
(TCV< 64) = 5 (0101)
(TCV< 128) = 6 (0110)
...
(TCV< 512) = 8 (1000)
...
(65,536< TVC > 131,072) = 16 (0001_0000)
...
Scale = 31 is TCV 2.14 Billion. The max number an NWN int can be. ( 0001_1111)
It looks to me that if you used:
Scale = log( TCV * 2 ) / log(2)
You would never go over 8 bits.
#8
Posté 08 décembre 2012 - 06:42
Bits (which was my original idea) are too linear. The threshold values for a placeable to spawn are simply too high at the low end and to low at the high end.
Numbers, on the other hand start out too slow and finish t0o large. Also, I want that overflow placeable triggered for amounts over the top end.
Still, the second progression is closer to what I envision. I was hoping to do this elegantly, but I think in the end a simple (but long) case statement will be a lot easier to read and implement :-/
The kind of progression I was looking for is something like:
Bits set # Value 00000000 0 TCV = 0 00000001 1 100< TCV (10^2) 00000010 2 625< TCV (25^2) 00000100 3 2,500< TCV (50^2) 00001000 4 5,625<TCV (75^2) 00010000 5 10,000<TCV (100^2) 00100000 6 62,500<TCV (250^2) 01000000 7 250,000<TCV (500^2) 10000000 8 562,500<TCV (750^2)with TCV over 1 million triggering the overflow (#9) placeable.
And the remainders would be examined to spawn lesser placeables. I.e. A TCV of 300,000 would generate #7 (250,00gp) and #1-5, but *not* #6 (remainder was less than 62,500).
<...on the picket fence>
#9
Posté 10 décembre 2012 - 04:05
Scale = (-1500.0 +sqrt(pow(1500.0, 2.0) - 8*(1402-TCV))) / 4
It produces:
Bit 0 = 100
Bit 1 = 1606
Bit 2 = 4630
Bit 3 = 10726
Bit 4 = 23110
Bit 5 = 48646
Bit 6 = 102790
Bit 7 = 223366
Bit 8 = 513670
Bit 9 = 1290886
#10
Posté 10 décembre 2012 - 07:11
#11
Posté 11 décembre 2012 - 06:57
Here are some quickly thrown together functions. ( meaning I have done no testing)
const string ResRefPrefix = "???" ;
int GetPlacableFlags( object oChest = OBJECT_SELF)
{
int nGPValue;
object oItem = GetFirstItemInInventory( oChest );
while (GetIsObjectValid(oItem))
{
nGPValue += GetGoldPieceValue(oItem);
oItem = GetNextItemInInventory (oChest);
}
return FloatToInt((-1500.0 +sqrt(pow(1500.0, 2.0) - 8*(1402-nGPValue))) / 4);
// FloatToInt(log(nGPValue*2.0)/log(2.0));
}
int GetCurrentdrawnPLCSet( object oChest = OBJECT_SELF)
{
return GetLocalInt( oChest,"PLC_Drawn_set");
}
void StoreCurrentdrawnPLCSet( int nDrawnSet, object oChest = OBJECT_SELF )
{
SetLocalInt( oChest,"PLC_Drawn_set",nDrawnSet);
}
void DestroyPLCsInSet(int nSet, object oChest =OBJECT_SELF)
{
string sTagPreFix = ObjectToString(oChest);
while(nSet)
{
int nFlag = nSet & -nSet;
nSet ^= nFlag;
DestroyObject( GetObjectByTag(sTagPreFix + IntToString(nFlag)));
}
}
void DrawPLCsInSet(int nSet, object oChest =OBJECT_SELF )
{
string sTagPreFix = ObjectToString(oChest);
string sResRef, sTag;
while(nSet)
{
int nFlag = nSet & -nSet;
nSet ^= nFlag;
sTag = sTagPreFix + IntToString(nFlag);
nFlag = FloatToInt( log(nFlag*1.0)/log(2.0));
sResRef = ResRefPrefix +IntToString(nFlag);
location lLoc = GetLocation(oChest);
CreateObject( OBJECT_TYPE_PLACEABLE, sResRef, lLoc, FALSE, sTag );
}
}
void UpdateTresurePlacables(object oTresureContainer = OBJECT_SELF)
{
int nOldSet = GetCurrentdrawnPLCSet(oTresureContainer);
int nNewSet = GetPlacableFlags(oTresureContainer);
int nChange = nOldSet ^ nNewSet;
if ( nChange )
{
StoreCurrentdrawnPLCSet( nNewSet, oTresureContainer);
DestroyPLCsInSet(nChange & nOldSet ,oTresureContainer );
DrawPLCsInSet (nChange & nNewSet ,oTresureContainer );
}
}
void main()
{
UpdateTresurePlacables();
}
#12
Posté 11 décembre 2012 - 11:03
1) Adjust the location where the placable is drawn. I just was not sure where you wanted them drawn.
2) Mask out overflow bits. ( Oversite. And the formula still need a little adjusting to get it down to 9 bits.)
#13
Posté 31 décembre 2012 - 10:00
I am speechless! <hardly>
I am agog! <well, *that's true>
I am absolutely amazed! <you are really overdoing it>
Er, yes.
LF, your script (with the right resref prefix) worked. It worked without errors. It worked without errors the *first* time. <whoa, old man. breathe. sit down. pour some brandy>

I mean... that's *never* happened before. <out with the bad, in with the good. drink>
Absolutely incredible.. *choke* *gasp* What?! Bother! <snail, boss. it's good for the heart ;->
Ack! <you really should help aluvian with that dragon>
Nonesense. She's a professional apprentice. It's what I pay her for. <assistant>
Assistant, apprentice. Yada yada. <the dragon will keep argentiel's hoard...>
Ack! Don't just flap there, bird! *Do* something! The poor lass is...
<...getting mangled by a mist dragon>
#14
Posté 31 décembre 2012 - 10:09
I spoke too soon. <always do>
adding or subtracting gold does nothing. Only items...
And the formula isn't right... It takes a couple diamonds of preposterous value (2,000,000 each) and still doesn't flinch.
(I.e. with 4 million+ inside, I still haven't seen tier 7, 8 or 9...)
Edit: Triggered 8 with about 10 million in it. (guessing... it was a *lot* of Gems of Preposterous Price).
Edit 2: wrap around on the gems... 32K each, not 2 mil :-P
It doesn't show level 1 (a couple coins) until there's 3,000 (3 sapphires) inside.
Level 1 (or *a* level) should show if *anything* is inside.
Edit 3: Ok, the top end of the formula works, but it still takes an awful lot of value before the first few coins show. And gold doesn't count... so, when you can... :-P
<...for the money>
Modifié par Rolo Kipp, 01 janvier 2013 - 01:40 .
#15
Posté 01 janvier 2013 - 12:37
/* Set oPlace's appearance. Will not update for PCs until they re-enter the area. */ int SetPlaceableAppearance (object oPlace, int nApp);
IIRC acaos and I tried varied ways around this, like setting things to cutscene invisible and back, to no avail. With critters, you can apply a very short polymorph effect to force the client to re-render (the basis of our !render command for the occasional single-client invisible critter caused by desync), but not with places.
As a result, the function is less useful than it could be, though it's still great for DMs designing areas wanting to see what various vfx look like applied near/on various placeable appearances - if you're using SIMTools you can dm_setvarstring NWNX!FUNCS!SETPLACEABLEAPPEARANCE *, where * is the appy number, on the fly - good fun.
Funky
#16
Posté 01 janvier 2013 - 12:45
While not needed for this (though that was my original thought), that could come in pretty handy for my Reg Mods... Especially making trees diseased or covered in webs...
Thanks, FS :-)
<...to get rolling with nwnx in 2013>
#17
Posté 01 janvier 2013 - 01:56
I have been playing with placeables that use models with the tile classification and an aabb mesh, and noticed that they will override or at least influence the Z values of the underlying tile''s aabb mesh if set to static. Typical placeables also have PWKs of course. So I was wondering if all that would come into play with the NWNX function you posted.
#18
Posté 01 janvier 2013 - 03:57
FloatToInt(-375.0 + sqrt(2262000 + 8.0*nGPValue) / 4);
Ill test it in a bit myself also.
Modifié par Lightfoot8, 01 janvier 2013 - 06:07 .
#19
Posté 01 janvier 2013 - 05:25
henesua wrote...
Funky, what does the change of appearance do? Is it just the look of the thing or will it also use all aspects of the model and apply it?
I have been playing with placeables that use models with the tile classification and an aabb mesh, and noticed that they will override or at least influence the Z values of the underlying tile''s aabb mesh if set to static. Typical placeables also have PWKs of course. So I was wondering if all that would come into play with the NWNX function you posted.
I have all this secondhand from acaos, but it's accurate so far as I know. When set to static, NWN 'bakes' places into an area's tiles in a fashion similar to the eponymous NWN2 function, though not identical. This helps optimize the areas for all sorts of purposes, most especially pathing. When you spawn in places, you lose that optimization, whether or not the new places are set to 'static' - but it's not the end of the world. When you spawn them in popular thoroughfares with pwks, it's not great, but we still do it with our wall spells, and while it does sometimes create some lag, it's not so bad that we feel the need to do something about it - and we're fairly picky in that regard.
Incidentally, if memory serves, spawned in places set to static are unlike toolset-placed static places in other regards as well - I seem to remember them being reachable with nwscript.
When you use the nwnx placeable appearance setting, you get the whole kit-and-kaboodle - it swaps to the new appy and accompanying pwk. It's little different from spawning in a new place and wiping the old one - save that you don't need a place with that appy to spawn in. If you're building areas with a ton of vfx applied on or around places, it's incredibly valuable for seeing how things will look on the fly - a single useable placeable can stand in for any appearance you need, instantly allowing you to tell which vfx (by way of dm_vfx) will show on it, and how they look. Past that, I'm not sure what you could do with it.
Dynamically changing placeable appearances has long been a point of difficulty for NWN - I remember someone trying to figure out a horse-and-carriage setup. Without making creatures with placeable appearances, it's hard to get anything that looks credible.
Funky
#20
Posté 01 janvier 2013 - 08:11
the progression is now:
bit0 = 2
bit1 = 1508
bit2 = 4532
bit3 = 10628
bit4 = 23012
bit5 = 48548
bit6 = 102692
bit7 = 223268
bit8 = 513572
bit9 = 1290788
And Keep in mind that the bits are 0 based, Your first placable ResRef should be: ResRefPrefix + "0" not ResRefPrefix + "1";
Corrections made to the script:
-Added a Filter to stop Total Chest Values of 3631652gp or more from filtering into the 10th bit and removing lower set bits.
-Added Code to catch the value of gold added to the chest.
-Added code to Value unidentified items at there full cost, not there unidentified value.
-Added an underline in the Created Placable Tags to advoid possiable Hash collision.
Here is the adjusted code. My testing showed it all working.
EDIT: Location of placables is still right on top of the old one in my code.
/////////////////////////////////////////////////
const string ResRefPrefix = "???" ;
int GetPlacableFlags( object oChest = OBJECT_SELF)
{
int nGPValue,bID;
object oItem = GetFirstItemInInventory( oChest );
while (GetIsObjectValid(oItem))
{
bID = GetIdentified(oItem);
SetIdentified(oItem,TRUE);
nGPValue += GetGoldPieceValue(oItem);
if ( GetBaseItemType(oItem) == BASE_ITEM_GOLD)
nGPValue += GetItemStackSize(oItem);
SetIdentified(oItem,bID);
oItem = GetNextItemInInventory (oChest);
}
int seReturn = FloatToInt(-375.0 + sqrt(2262000 + 8.0*nGPValue) / 4);
if ( seReturn > 0x3ff) seReturn = 0x3ff;
return seReturn;
// FloatToInt(log(nGPValue*2.0)/log(2.0));
}
int GetCurrentdrawnPLCSet( object oChest = OBJECT_SELF)
{
return GetLocalInt( oChest,"PLC_Drawn_set");
}
void StoreCurrentdrawnPLCSet( int nDrawnSet, object oChest = OBJECT_SELF )
{
SetLocalInt( oChest,"PLC_Drawn_set",nDrawnSet);
}
void DestroyPLCsInSet(int nSet, object oChest =OBJECT_SELF)
{
string sTagPreFix = ObjectToString(oChest);
while(nSet)
{
int nFlag = nSet & -nSet;
nSet ^= nFlag;
DestroyObject( GetObjectByTag(sTagPreFix + "_" + IntToString(nFlag)));
//SpeakString( "Destroying Placable with tag :" + sTagPreFix+ "_" + IntToString(nFlag));
}
}
void DrawPLCsInSet(int nSet, object oChest =OBJECT_SELF )
{
string sTagPreFix = ObjectToString(oChest);
string sResRef, sTag;
while(nSet)
{
int nFlag = nSet & -nSet;
nSet ^= nFlag;
sTag = sTagPreFix + "_" + IntToString(nFlag);
nFlag = FloatToInt( log(nFlag*1.0)/log(2.0));
sResRef = ResRefPrefix +IntToString(nFlag);
location lLoc = GetLocation(oChest);
CreateObject( OBJECT_TYPE_PLACEABLE, sResRef, lLoc, FALSE, sTag );
//SpeakString("Creating placable :" + sResRef + " Tag :" +sTag);
}
}
void UpdateTresurePlacables(object oTresureContainer = OBJECT_SELF)
{
int nOldSet = GetCurrentdrawnPLCSet(oTresureContainer);
int nNewSet = GetPlacableFlags(oTresureContainer);
int nChange = nOldSet ^ nNewSet;
if ( nChange )
{
StoreCurrentdrawnPLCSet( nNewSet, oTresureContainer);
DestroyPLCsInSet(nChange & nOldSet ,oTresureContainer );
DrawPLCsInSet (nChange & nNewSet ,oTresureContainer );
}
}
void main()
{
UpdateTresurePlacables();
}
Modifié par Lightfoot8, 01 janvier 2013 - 08:19 .
#21
Posté 01 janvier 2013 - 05:12
Ah, yes. 10 bits, not 9. Starting at 0. *sigh*
Okay, moved 1,2 &3 down one and will make a new Number 3.
Works :-) Thank you LF!
<...work order for the dwarf>





Retour en haut






