Author Topic: A few things I've done with lua.cpp  (Read 6397 times)

0 Members and 1 Guest are viewing this topic.

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
A few things I've done with lua.cpp
The result of some work I did with the FS2 code to make possible some things I wanted for the RTS Mod, this patch exposes the following 3 functions to scripting:

1. boolean Ship.isWarpingIn()
True if the ship is warping in (i.e. blue on the radar)

2. int gr.drawModel(model, position, orientation)
Draws the model. Nonzero return values are errors, returns 0 if successful. Note, this function is basically just meant to simulate the function WMCoolmon came up with, but which doesn't seem to have been committed to trunk.

3. int,int,int,int gr.drawTargetingBrackets(Object object, [boolean draw=true, int padding=5])
Draws targeting brackets around a model (or optionally doesn't). Returns the left, top, right, and bottom edge coordinates.

I am also thinking about making a more generalized ship.flags and possibly ship class flags getter function, because I reckon there's a lot that could be done with that.

* Aardwolf expresses an interest in working with the SCP

File contents of the .patch file:
Code: [Select]
Index: lua.cpp
===================================================================
--- lua.cpp (revision 5301)
+++ lua.cpp (working copy)
@@ -11,10 +11,12 @@
 #include "graphics/font.h"
 #include "globalincs/linklist.h"
 #include "globalincs/pstypes.h"
+#include "hud/hudbrackets.h"
 #include "iff_defs/iff_defs.h"
 #include "io/key.h"
 #include "io/mouse.h"
 #include "io/timer.h"
+#include "jumpnode/jumpnode.h"
 #include "lighting/lighting.h"
 #include "mission/missioncampaign.h"
 #include "mission/missiongoals.h"
@@ -6060,6 +6062,25 @@
  return ADE_RETURN_TRUE;
 }
 
+// Aardwolf's function for finding if a ship should be drawn as blue on the radar/minimap
+ADE_FUNC(isWarpingIn, l_Ship, NULL, "Checks if ship is warping in", "boolean", "True if the ship is warping in, false or nil otherwise")
+{
+ object_h *objh;
+ if(!ade_get_args(L, "o", l_Ship.GetPtr(&objh)))
+ return ADE_RETURN_NIL;
+
+ if(!objh->IsValid())
+ return ADE_RETURN_NIL;
+
+ ship *shipp = &Ships[objh->objp->instance];
+ if(shipp->flags & SF_ARRIVING_STAGE_1)
+ {
+ return ADE_RETURN_TRUE;
+ }
+
+ return ADE_RETURN_FALSE;
+}
+
 //**********HANDLE: Weapon
 ade_obj<object_h> l_Weapon("weapon", "Weapon handle", &l_Object);
 
@@ -8053,6 +8074,159 @@
  return ADE_RETURN_TRUE;
 }
 
+// Aardwolf's test code to render a model, supposed to emulate WMC's gr.drawModel function
+ADE_FUNC(drawModel, l_Graphics, "model, position, orientation", "Draws the given model with the specified position and orientation", "int", "Zero if successful, otherwise an integer error code")
+{
+ model_h *mdl = NULL;
+ vec3d *v = &vmd_zero_vector;
+ matrix_h *mh = NULL;
+ if(!ade_get_args(L, "ooo", l_Model.GetPtr(&mdl), l_Vector.GetPtr(&v), l_Matrix.GetPtr(&mh)))
+ return ade_set_args(L, "i", 1);
+
+ if(mdl == NULL)
+ return ade_set_args(L, "i", 2);
+
+ int model_num = mdl->GetID();
+ if(model_num < 0)
+ return ade_set_args(L, "i", 3);
+
+ //Handle angles
+ matrix *orient = mh->GetMatrix();
+
+ //Clip
+ gr_set_clip(0, 0, gr_screen.max_w, gr_screen.max_h, false);
+
+ //Handle 3D init stuff
+ g3_start_frame(1);
+
+ vec3d cam_pos;
+ matrix cam_orient;
+
+ camid cid = cam_get_current();
+ cid.getCamera()->get_info(&cam_pos, &cam_orient);
+
+ g3_set_view_matrix(&cam_pos, &cam_orient, View_zoom);
+
+ if (!Cmdline_nohtl) {
+ gr_set_proj_matrix( Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
+ gr_set_view_matrix(&Eye_position, &Eye_matrix);
+ }
+
+ //Draw the ship!!
+ model_clear_instance(model_num);
+ model_set_detail_level(0);
+ model_render(model_num, orient, v, MR_NORMAL);
+
+ //OK we're done
+ if (!Cmdline_nohtl)
+ {
+ gr_end_view_matrix();
+ gr_end_proj_matrix();
+ }
+
+ //Bye!!
+ g3_end_frame();
+ gr_reset_clip();
+
+ return ade_set_args(L, "i", 0);
+}
+
+// Aardwolf's targeting brackets function
+ADE_FUNC(drawTargetingBrackets, l_Graphics, "object Object, [boolean draw=true, int padding=5]",
+ "Gets the edge positions of targeting brackets for the specified object. The brackets will only be drawn if draw is true or the default value of draw is used. Brackets are drawn with the current color. The brackets will have a padding (distance from the actual bounding box); the default value (used elsewhere in FS2) is 5.",
+ "number,number,number,number",
+ "Left, top, right, and bottom positions of the brackets, or nil if invalid")
+{
+ if(!Gr_inited) {
+ return ADE_RETURN_NIL;
+ }
+
+ object_h *objh = NULL;
+ bool draw_box = true;
+ int padding = 5;
+
+ if( !ade_get_args(L, "o|bi", l_Object.GetPtr(&objh), &draw_box, &padding) ) {
+ return ADE_RETURN_NIL;
+ }
+
+ // The following code is mostly copied from
+ // void hud_show_brackets(object *targetp, vertex *projected_v)
+ // in hudtarget.cpp
+
+ if( !objh->IsValid()) {
+ return ADE_RETURN_NIL;
+ }
+
+ object *targetp = objh->objp;
+
+ int x1,x2,y1,y2;
+ int bound_rc;
+
+ int modelnum;
+
+ switch ( targetp->type ) {
+ case OBJ_SHIP:
+ modelnum = Ship_info[Ships[targetp->instance].ship_info_index].model_num;
+ bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
+ if ( bound_rc != 0 ) {
+ return ADE_RETURN_NIL;
+ }
+ break;
+
+ case OBJ_DEBRIS:
+ modelnum = Debris[targetp->instance].model_num;
+ bound_rc = submodel_find_2d_bound_min( modelnum, Debris[targetp->instance].submodel_num, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
+ if ( bound_rc != 0 ) {
+ return ADE_RETURN_NIL;
+ }
+ break;
+
+ case OBJ_WEAPON:
+ Assert(Weapon_info[Weapons[targetp->instance].weapon_info_index].subtype == WP_MISSILE);
+ modelnum = Weapon_info[Weapons[targetp->instance].weapon_info_index].model_num;
+ bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
+ break;
+
+ case OBJ_ASTEROID:
+ {
+ int pof = 0;
+ pof = Asteroids[targetp->instance].asteroid_subtype;
+ modelnum = Asteroid_info[Asteroids[targetp->instance].asteroid_type].model_num[pof];
+ bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
+ }
+ break;
+
+ case OBJ_JUMP_NODE:
+ modelnum = targetp->jnp->get_modelnum();
+ bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
+ break;
+
+ default:
+ // should never happen
+ Int3();
+ return ADE_RETURN_NIL;
+ }
+
+ x1 -= padding;
+ x2 += padding;
+ y1 -= padding;
+ y2 += padding;
+ if ( draw_box ) {
+ if( !(g3_in_frame() > 0) )
+ {
+ g3_start_frame(0);
+ draw_brackets_square(x1, y1, x2, y2, false);
+ g3_end_frame();
+ }
+ else
+ {
+ draw_brackets_square(x1, y1, x2, y2, false);
+ }
+ }
+
+ return ade_set_args(L, "iiii", x1, y1, x2, y2);
+}
+
 #define MAX_TEXT_LINES 256
 static char *BooleanValues[] = {"False", "True"};
 static const int NextDrawStringPosInitial[] = {0, 0};

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: A few things I've done with lua.cpp
Nice. Very nice. :yes:


With flags there is the problem that game uses (mostly) single bits as flags. This means you either need to include code the 'decypher' the one or two ints containing the flags before handing the processed lot over to script or then try to provide good enough documentation so that it would be enough to use just the int.
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: A few things I've done with lua.cpp
heres a couple lua funcs i added

Code: [Select]
ADE_FUNC(isAfterburnerActive, l_Physics, NULL, "True if Afterburners are on, false or nil if not", "boolean", "Detects whether afterburner is active")
{
physics_info_h *pih;
if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
return ADE_RETURN_NIL;

if(!pih->IsValid())
return ade_set_error(L, "b", false);

if (pih->pi->flags & PF_AFTERBURNER_ON)
return ade_set_args(L, "b",  true);
else
return ade_set_args(L, "b",  false);
}

if you ned to see if the afterburner is on or not, just call the function and it will return a bool

Code: [Select]
ADE_FUNC(renderTechModel2, l_Shipclass, "X1, Y1, X2, Y2, orientation Orientation=null, [Zoom multiplier]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
{
int x1,y1,x2,y2;
int idx;
float zoom = 1.3f;
matrix_h *mh = NULL;
if(!ade_get_args(L, "oiiiio|f", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2,  l_Matrix.GetPtr(&mh), &zoom))
return ade_set_error(L, "b", false);

if(idx < 0 || idx > Num_ship_classes)
return ade_set_args(L, "b", false);

if(x2 < x1 || y2 < y1)
return ade_set_args(L, "b", false);

ship_info *sip = &Ship_info[idx];

//Make sure model is loaded
sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0], 0);

if(sip->model_num < 0)
return ade_set_args(L, "b", false);

//Handle angles
matrix *orient = mh->GetMatrix();

//Clip
gr_set_clip(x1,y1,x2-x1,y2-y1,false);

//Handle 3D init stuff
g3_start_frame(1);
g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * zoom);

if (!Cmdline_nohtl) {
gr_set_proj_matrix( Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
gr_set_view_matrix(&Eye_position, &Eye_matrix);
}

//Handle light
light_reset();
vec3d light_dir = vmd_zero_vector;
light_dir.xyz.y = 1.0f;
light_add_directional(&light_dir, 0.65f, 1.0f, 1.0f, 1.0f);
light_rotate_all();

//Draw the ship!!
model_clear_instance(sip->model_num);
model_set_detail_level(0);
model_render(sip->model_num, orient, &vmd_zero_vector, MR_LOCK_DETAIL | MR_AUTOCENTER | MR_NO_FOGGING);

//OK we're done
if (!Cmdline_nohtl)
{
gr_end_view_matrix();
gr_end_proj_matrix();
}

//Bye!!
g3_end_frame();
gr_reset_clip();

return ade_set_args(L, "b", true);
}

this varient of render tech model excepts a matrix rather than an odball set of percentages

I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline redsniper

  • 211
  • Aim for the Top!
Re: A few things I've done with lua.cpp
gr.drawModel
YES! Put this back in the official builds please! :D
"Think about nice things not unhappy things.
The future makes happy, if you make it yourself.
No war; think about happy things."   -WouterSmitssm

Hard Light Productions:
"...this conversation is pointlessly confrontational."

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Well I was talking to Nuke trying to make sense of why he wanted his own render model function, and I eventually got what he was saying. My function uses world-space coordinates, whereas his is camera-space, and suited better for drawing stuff like the techroom ships or the target view ship render.

gr.drawModel
YES! Put this back in the official builds please! :D

Unfortunately I'm not in charge of that (I'm not an SCP team-member ... yet). But yeah, I was almost certain it already had been implemented, and kind of disappointed to not be able to find it. So I made one of my own, which basically worked the same way as WMC's (at least for the user, as far as the code for it I can't say it works the same way internally).

 

Offline karajorma

  • King Louie - Jungle VIP
  • Administrator
  • 214
    • Karajorma's Freespace FAQ
Re: A few things I've done with lua.cpp
Unfortunately I'm not in charge of that (I'm not an SCP team-member ... yet).

So apply to join us. :)
Karajorma's Freespace FAQ. It's almost like asking me yourself.

[ Diaspora ] - [ Seeds Of Rebellion ] - [ Mind Games ]

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
What sort of application are we talking about?  :drevil:

A further addition to lua.cpp:

Code: [Select]
// Aardwolf's modified forceMousePosition function, because the other one doesn't work some reason
ADE_FUNC(setCursorPosition, l_Mouse, "x, y", "moves the cursor to the given coordinates\nshould also do everything forceMousePosition would do", "boolean", "true if it worked, false otherwise")
{
if(!mouse_inited)
return ADE_RETURN_FALSE;

if(!Gr_inited)
return ADE_RETURN_FALSE;

int x, y;
if (!(ade_get_args(L, "ii", &x, &y)))
return ADE_RETURN_FALSE;

if (!((x >= 0) && (x <= gr_screen.max_w)))
return ADE_RETURN_FALSE;

if (!((y >= 0) && (y <= gr_screen.max_h)))
return ADE_RETURN_FALSE;

mouse_set_pos(x, y);

return ADE_RETURN_TRUE;
}

Basically, the io.forceMousePosition function doesn't seem to be doing anything. It returns true, which it says means it's working, but there's no visible effect. Since I wasn't able to find anything about it by searching the forums, and Wanderer wasn't on IRC (I was under the impression he might know what it was supposed to do), I wrote my own.

I'm still testing this, though.

Edit: It appears to work as intended, but I'll need to change how I'm using it because it's not syncing right.

Edit, The Second: And for some stupid reason the "On Mouse Moved" hook is never being called. I'm looking into this now.
« Last Edit: June 07, 2009, 11:00:21 pm by Aardwolf »

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Well, the function (see above) works better than the existing one (which had no visible effects), but the goal I thought I could use it for seems unachievable.

The conditional hook $On Mouse Moved: doesn't execute (but if there are parse errors it complains about them), and I couldn't figure out why.

Also, my attempt to get around this problem by putting the code I had there in its own function and calling it a) in the global $Simulation: hook and b) in the conditional $On HUD Draw: hooks didn't work out, because the cursor wouldn't stay still.

While I could in theory achieve what I'm aiming for by manually drawing the cursor, I'm not sure I want to do that. Since this is turning into mod-specific comments, I'm not going to spend too much more effort describing it, at least not in this thread. I would however, like to summarize with the following list of observations:

  • The On Mouse Moved never runs (or at least doesn't seem to.
  • The io.forceMousePosition function doesn't seem to do anything.
  • The function I wrote at least does what the aforementioned function seems like it is meant to do, although I can't guarantee my implementation is flawless either.

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: A few things I've done with lua.cpp
io.forceMousePosition works fine in my mouse script when running the script (slightly modified) in trunk build.
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: A few things I've done with lua.cpp
on something unrelated i might want to be able to iterate through all game objects rather than just ships or weapons for things like physics scripts. working on the atmospherics and orbital mechanics script leads me to believe that its a real pain in the ass to iterate through each kind of object in the game, when you're essentially doing the same thing to every object in the game the result is 4 loops that do the same thing. what i need is mn.Objects[].

the other thing i might do is add a function to get any objects obj_num. its good if you need to uniquely identify any object in the game without the luxury of a unique name. i had to code one for weapons because theres no way to tag custom meta info to an instance of a weapon. in doing so i found that it would be really awesome if every type of object had this function. adding this shoud just be a simple cut and paste job, but id like to add it at the object level.

since im doing so much to rape the less than realistic physics that freespace uses, mutilating their carcass and replacing it with an ultra realistic piece of scripting genious. it would be kind of awesome if i can disable them all together. it may also be necessary to be able to call collision detection functions, possibly modified to work without upper limits on how fast things can go.

opinions?
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: A few things I've done with lua.cpp
Might as well start applying these changes...

These all seem perfectly reasonable

Quote
boolean Ship.isWarpingIn()
int gr.drawModel(model, position, orientation)
int,int,int,int gr.drawTargetingBrackets(Object object, [boolean draw=true, int padding=5])

isAfterburnerActive

Is the alternate tech model render necessary as there already is a tech model render function?

Also i changed the forceMousePosition to use mouse_set_pos instead of mouse_force_pos as it appears that there are differences between debug and release builds on how mouse is handled.
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: A few things I've done with lua.cpp
Might as well start applying these changes...

These all seem perfectly reasonable

Quote
boolean Ship.isWarpingIn()
int gr.drawModel(model, position, orientation)
int,int,int,int gr.drawTargetingBrackets(Object object, [boolean draw=true, int padding=5])

isAfterburnerActive

Is the alternate tech model render necessary as there already is a tech model render function?

Also i changed the forceMousePosition to use mouse_set_pos instead of mouse_force_pos as it appears that there are differences between debug and release builds on how mouse is handled.

rendertechmodel2 uses a matrix instead of %rotation. i created it mainly so i could do a semi-3d attitude indicator which required some matrix magic in order to look right. i was looking at the possibility of overloading the existing function to take either a matrix, eulers, or the default percentages. but that doesnt seem likely without completely changing the parameters around as far as i can tell. my version really only changes a few lines of code. on the other hand its something that i can think of 50 other uses for and it really simplifies things in the long run.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Wanderer

  • Wiki Warrior
  • 211
  • Mostly harmless
Re: A few things I've done with lua.cpp
OK then.. valid enough reasoning.. I'll try to commit all these when i have time - possibly today
Do not meddle in the affairs of coders for they are soggy and hard to light

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Yay... Question: will my modified versions realize that the commit is a commit of my stuff, or will I have to do some messing around to get that working right?

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
I noticed just now that this crashes. I've figured out what's wrong and made a patch:

targetingbrackets_crash_fix.patch
Code: [Select]
Index: lua.cpp
===================================================================
--- lua.cpp (revision 5392)
+++ lua.cpp (working copy)
@@ -8447,11 +8447,20 @@
  int bound_rc, pof;
  int modelnum;
 
+ bool not_in_frame = !(g3_in_frame() > 0);
+
+ if( not_in_frame ) {
+ g3_start_frame(0);
+ }
+
  switch ( targetp->type ) {
  case OBJ_SHIP:
  modelnum = Ship_info[Ships[targetp->instance].ship_info_index].model_num;
  bound_rc = model_find_2d_bound_min( modelnum, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
  if ( bound_rc != 0 ) {
+ if( not_in_frame ) {
+ g3_end_frame();
+ }
  return ADE_RETURN_NIL;
  }
  break;
@@ -8459,6 +8468,9 @@
  modelnum = Debris[targetp->instance].model_num;
  bound_rc = submodel_find_2d_bound_min( modelnum, Debris[targetp->instance].submodel_num, &targetp->orient, &targetp->pos,&x1,&y1,&x2,&y2 );
  if ( bound_rc != 0 ) {
+ if( not_in_frame ) {
+ g3_end_frame();
+ }
  return ADE_RETURN_NIL;
  }
  break;
@@ -8487,15 +8499,11 @@
  y1 -= padding;
  y2 += padding;
  if ( draw_box ) {
- if( !(g3_in_frame() > 0) ) {
- g3_start_frame(0);
- draw_brackets_square(x1, y1, x2, y2, false);
- g3_end_frame();
- }
- else {
- draw_brackets_square(x1, y1, x2, y2, false);
- }
+ draw_brackets_square(x1, y1, x2, y2, false);
  }
+ if( not_in_frame ) {
+ g3_end_frame();
+ }
 
  return ade_set_args(L, "iiii", x1, y1, x2, y2);
 }


I'm also uploading it as an attachment so it's easier to download. The above version is basically just so if the attachment dies, it's still here.

[attachment deleted by MSC

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Mantised, as per a suggestion by blowfish.

Edit: link: http://scp.indiegames.us/mantis/view.php?id=1949

Edit II: and for some stupid reason Mantis assigned it to WMCoolmon automagically, even though he's AWOL for an indeterminate duration...
« Last Edit: July 03, 2009, 09:43:51 am by Aardwolf »

 
Re: A few things I've done with lua.cpp
Mantised, as per a suggestion by blowfish.

Edit: link: http://scp.indiegames.us/mantis/view.php?id=1949

Edit II: and for some stupid reason Mantis assigned it to WMCoolmon automagically, even though he's AWOL for an indeterminate duration...

Patch committed, and unmantised from WMC
STRONGTEA. Why can't the x86 be sane?

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Ah good

 

Offline Nuke

  • Ka-Boom!
  • 212
  • Mutants Worship Me
Re: A few things I've done with lua.cpp
heres a new one i just did

Code: [Select]
ADE_FUNC(getSignature, l_Object, NULL, "Gets the object's unique signature", "number", "Returns the objects unique numeric signature, useful for creating a metadata sytem")
{
object_h *oh;
if(!ade_get_args(L, "o", l_Object.GetPtr(&oh)))
return ade_set_error(L, "i", 0);

if(!oh->IsValid())
return ade_set_error(L, "i", 0);

return ade_set_args(L, "i", oh->objp->signature);
}

it gets an object's unique signature (regaurdless of its breed). you can use this to make a global metadata system that is object type independent.
I can no longer sit back and allow communist infiltration, communist indoctrination, communist subversion, and the international communist conspiracy to sap and impurify all of our precious bodily fluids.

Nuke's Scripting SVN

 

Offline Aardwolf

  • 211
  • Posts: 16,384
    • Minecraft
Re: A few things I've done with lua.cpp
Does that work? I mean, if an object becomes invalid, will it avoid using the same value for any new objects?