11package script .developer ;
22
3+ import script .dictionary ;
34import script .library .sui ;
45import script .library .utils ;
56import script .location ;
67import script .obj_id ;
8+ import script .transform ;
79
810import java .io .IOException ;
9- import java .io .PrintWriter ;
10- import java .nio .charset .StandardCharsets ;
1111import java .util .Arrays ;
12- import java .util .List ;
1312
1413/**
1514 * SWG Buildout Utility
1615 * For World Building in the Release Game Client
1716 * To Use: attach developer.buildout_utility to your player and say "info" for commands
18- *
17+ * <p>
1918 * Most usage will be creating an object either with this script or by some other means,
2019 * targeting it, and saying "getBuildoutInfo" in spatial which will give you an SUI window
2120 * of everything you need to type in to add that object to a buildout.
22- *
21+ * <p>
2322 * *************************************************
2423 * This is a WORK IN PROGRESS
2524 * I'm adding it now upon request to help a few people get the gist of buildouts.
2625 * *************************************************
27- *
26+ * <p>
2827 * Authors: Aconite
2928 */
3029public class buildout_utility extends script .base_script {
3130
32- public buildout_utility ()
33- {
31+ public buildout_utility () {
32+
3433 }
3534
36- // Only list planets in the SCENES array that are full size (16000x16000)
37- // Only worlds at full size using -8192 to 8192 coordinates should be used otherwise the positioning will be off because the buildout names won't match to the correct positioning boxes.
38- public static final String [] SCENES = {
39- "tatooine" ,
40- "yavin4" ,
41- "mustafar" ,
42- "endor" ,
43- "talus" ,
44- "corellia" ,
45- "rori" ,
46- "dathomir" ,
47- "dantooine" ,
48- "naboo" ,
49- "lok"
50- };
51-
5235 public int OnAttach (obj_id self ) throws InterruptedException {
5336 sendSystemMessageTestingOnly (self , "Buildout Utility Attached... say INFO for help." );
5437 return SCRIPT_CONTINUE ;
@@ -85,6 +68,10 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
8568 sendConsoleMessage (self , "returns all buildout information for the specified object" );
8669 sendConsoleMessage (self , "\\ #00ffff getObjects \\ #." );
8770 sendConsoleMessage (self , "returns all objects within 500m with buildout_utility.write objvar" );
71+ //sendConsoleMessage(self, "\\#00ffff setAllBuildOutObjVars \\#.");
72+ //sendConsoleMessage(self, "finds all objects in the buildout area and attaches buildout_utility.write objvar if not already attached");
73+ sendConsoleMessage (self , "\\ #00ffff updateServerBuildout \\ #." );
74+ sendConsoleMessage (self , "finds everything in the buildout area that does not have a buildout ID and writes it to a .tab file in the Linux directory" );
8875 //sendConsoleMessage(self, "\\#00ffff writeBuildout \\#bfff00 <file name> \\#.");
8976 //sendConsoleMessage(self, "writes all objects within 500m range with the buildout_utility.write objvar to a buildout formatted .csv file swg-main/linux/exe");
9077 sendConsoleMessage (self , "\\ #ffff00 ============ ============ ============ ============ \\ #." );
@@ -119,36 +106,92 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
119106 return SCRIPT_CONTINUE ;
120107 }
121108
122- List <String > list = Arrays .asList (SCENES );
123- if (!list .contains (getCurrentSceneName ())) {
124- sendSystemMessageTestingOnly (self , "You cannot use this feature in your current scene (likely due to world size mismatch)." );
125- return SCRIPT_CONTINUE ;
109+ StringBuilder sb = new StringBuilder ();
110+
111+ sb .append ("Buildout Information for Object: " ).append (oid ).append ("\n \n " );
112+
113+ if (hasObjVar (oid , "buildoutObjectId" )) {
114+ sb .append (getHeaderFormat ("Object ID in Buildout File" ));
115+ sb .append ("\t " ).append (getIntObjVar (oid , "buildoutObjectId" ));
116+ sb .append ("\n \n " );
126117 }
127118
128- location wp = getLocation (oid );
129- String buildout = getBuildoutAreaName (wp .x , wp .z );
130- float coord_x = wp .x - getBuildoutRootCoords (buildout ).x ;
131- float coord_z = wp .z - getBuildoutRootCoords (buildout ).z ;
132- obj_id cell = wp .cell ;
133- float [] q = getQuaternion (oid );
134- boolean isInBuilding = isIdValid (cell );
135- obj_id container = null ;
136- if (isInBuilding ) {
137- container = getContainedBy (cell );
119+ sb .append (getHeaderFormat ("Server Template" )).append ("\t " ).append (getTemplateName (oid )).append ("\n \n " );
120+ sb .append (getHeaderFormat ("Shared Template" )).append ("\t " ).append (getSharedObjectTemplateName (oid )).append ("\n \n " );
121+
122+ final location objectLoc = getLocation (oid );
123+ location topLoc = getLocation (oid );
124+ sb .append (getHeaderFormat ("Buildout Area" ));
125+ if (isIdValid (getTopMostContainer (oid ))) {
126+ topLoc = getLocation (getTopMostContainer (oid ));
127+ }
128+ final String buildoutAreaName = getBuildoutAreaName (topLoc .x , topLoc .z );
129+ sb .append ("\t " ).append (buildoutAreaName ).append ("\n \n " );
130+
131+ sb .append (getHeaderFormat ("Container" ));
132+ if (isIdValid (objectLoc .cell )) {
133+ // if the cell has a buildout object ID, we need to display that instead
134+ // because that's what actually goes in the buildout
135+ if (hasObjVar (objectLoc .cell , "buildoutObjectId" )) {
136+ sb .append ("\t " ).append (getIntObjVar (objectLoc .cell , "buildoutObjectId" ));
137+ } else {
138+ sb .append ("\t " ).append (objectLoc .cell );
139+ }
140+ } else {
141+ sb .append ("\t " ).append (0 );
142+ }
143+ sb .append ("\n \n " );
144+
145+ // Cell Index
146+ sb .append (getHeaderFormat ("Cell Index" ));
147+ sb .append ("\t " ).append (getCellIndex (objectLoc .cell ));
148+ sb .append ("\n \n " );
149+
150+ boolean isComposite = false ;
151+ // X Y Z coordinates
152+ float [] buildout = getBuildoutAreaSizeAndCenter (objectLoc .x , objectLoc .z , objectLoc .area , false , false );
153+ if (buildout == null || buildout .length < 3 ) {
154+ isComposite = true ;
155+ buildout = getBuildoutAreaRect (objectLoc .x , objectLoc .z , objectLoc .area , true );
156+ }
157+ sb .append (getHeaderFormat ("Object to Parent Coordinates (for Buildout) [pX, pY, pZ]" ));
158+ if (isIdValid (objectLoc .cell )) {
159+ sb .append ("\t " ).append (objectLoc .x ).append (",\n " );
160+ sb .append ("\t " ).append (objectLoc .y ).append (",\n " );
161+ sb .append ("\t " ).append (objectLoc .z ).append (",\n " );
162+ } else {
163+ if (isComposite ) {
164+ sb .append ("\t " ).append ((objectLoc .x - buildout [0 ])).append (",\n " );
165+ sb .append ("\t " ).append (objectLoc .y ).append (",\n " );
166+ sb .append ("\t " ).append ((objectLoc .z - buildout [2 ]));
167+ } else {
168+ sb .append ("\t " ).append ((objectLoc .x - (buildout [2 ] - (buildout [0 ] / 2 )))).append (",\n " );
169+ sb .append ("\t " ).append (objectLoc .y ).append (",\n " );
170+ sb .append ("\t " ).append ((objectLoc .z - (buildout [3 ] - (buildout [1 ] / 2 ))));
171+ }
138172 }
139- String message = "Buildout Information for Object: " + oid + "\n \n " +
140- "Reminder, this currently supports EXTERIOR objects only. Interiors should probably be using a dungeon_spawner or interior spawn egg anyways." + "\n \n " +
141- "template: " + getTemplateName (oid ) + "\n \n " +
142- "buildout: " + buildout + "\n \n " +
143- "cell ID: " + cell + "\n \n " +
144- "container: " + container + "\n \n " +
145- "world coordinates (X, Y, Z): " +wp .x +", " +wp .y +", " +wp .z + "\n \n " +
146- "buildout coordinates (X, Y, Z): " + coord_x +", " +wp .y +", " +coord_z +"\n \n " +
147- "quaternion (qW, qX, qY, qZ): " + q [0 ] + ", " + q [1 ] + ", " + q [2 ] + ", " + q [3 ] + " \n \n " +
148- "scripts: " + Arrays .toString (getScriptList (oid )) + "\n \n " +
149- "objvars: " + getPackedObjvars (oid );
150-
151- sui .msgbox (self , self , message , sui .OK_ONLY , "getBuildoutCoords" , "noHanlder" );
173+ sb .append ("\n \n " );
174+
175+ final float [] quaternion = getQuaternion (oid );
176+ sb .append (getHeaderFormat ("Quaternion [qW, qX, qY, qZ]" ));
177+ sb .append ("\t " ).append (quaternion [0 ]).append (",\n " );
178+ sb .append ("\t " ).append (quaternion [1 ]).append (",\n " );
179+ sb .append ("\t " ).append (quaternion [2 ]).append (",\n " );
180+ sb .append ("\t " ).append (quaternion [3 ]);
181+ sb .append ("\n \n " );
182+
183+ sb .append (getHeaderFormat ("Scripts" ));
184+ sb .append (Arrays .toString (getScriptList (oid )));
185+ sb .append ("\n \n " );
186+
187+ sb .append (getHeaderFormat ("ObjVars" ));
188+ sb .append (getPackedObjvars (oid ));
189+ sb .append ("\n \n " );
190+
191+ final int pid = sui .msgbox (self , self , sb .toString (), sui .OK_ONLY , "getBuildoutInfo" , sui .MSG_INFORMATION , "noHandler" );
192+ setSUIProperty (pid , "Prompt.lblPrompt" , "Editable" , "true" );
193+ setSUIProperty (pid , "Prompt.lblPrompt" , "GetsInput" , "true" );
194+ flushSUIPage (pid );
152195
153196 // ===========================================================================
154197 // ===== writeBuildout
@@ -208,7 +251,7 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
208251 count ++;
209252 }
210253
211- String header = "Listing all objects within 500m with buildout_utility.write objvar \n Total object count: " + count + "\n \n " ;
254+ String header = "Listing all objects within 500m with buildout_utility.write objvar \n Total object count: " + count + "\n \n " ;
212255 sui .msgbox (self , self , header + Arrays .toString (objects ), sui .OK_ONLY , "getObjects" , "noHandler" );
213256
214257 // ===========================================================================
@@ -245,19 +288,124 @@ public int OnSpeaking(obj_id self, String text) throws InterruptedException, IOE
245288 obj_id object = createObject (command2 , me );
246289 setObjVar (object , "buildout_utility.write" , 1 );
247290
248- if (isValidId (object )) {
291+ if (isValidId (object )) {
249292 sendSystemMessageTestingOnly (self , "createObject: Success, new object OID is " + object );
250293 } else {
251294 sendSystemMessageTestingOnly (self , "createObject: ERROR creating object. Check your template spelling." );
252295 }
253296
297+ return SCRIPT_CONTINUE ;
298+ } else if (command1 .equalsIgnoreCase ("getBuildoutAreaRect" )) {
299+ location loc = getLocation (self );
300+ float [] rect = getBuildoutAreaRect (loc .x , loc .z , loc .area , true );
301+ sendSystemMessageTestingOnly (self , "Area Rect (as x0, x1, y0, y1) is: " + rect [0 ] + ", " + rect [1 ] + ", " + rect [2 ] + ", " + rect [3 ]);
302+ } else if (command1 .equalsIgnoreCase ("getYaw" )) {
303+ sendSystemMessageTestingOnly (self , "Yaw is: " + getYaw (getTarget (self )));
304+ } else if (command1 .equalsIgnoreCase ("setYaw" )) {
305+ setYaw (getTarget (self ), Float .parseFloat (command2 ));
306+ } else if (command1 .equalsIgnoreCase ("getTransform" )) {
307+ transform t = getTransform_o2p (getTarget (self ));
308+ sendSystemMessageTestingOnly (self , t .getLocalFrameI_p ().toString ());
309+ sendSystemMessageTestingOnly (self , t .getLocalFrameJ_p ().toString ());
310+ sendSystemMessageTestingOnly (self , t .getLocalFrameK_p ().toString ());
311+ } else if (command1 .equalsIgnoreCase ("updateServerBuildout" )) {
312+ //get the current buildout area
313+ location here = getLocation (self );
314+ obj_id containingBuilding = getTopMostContainer (self );
315+ if (isIdValid (containingBuilding )) {
316+ here = getLocation (containingBuilding );
317+ }
318+ String buildoutAreaName = getBuildoutAreaName (here .x , here .z , getCurrentSceneName ());
319+ String sceneName = getCurrentSceneName ();
320+ sendSystemMessageTestingOnly (self , "Updating buildout for " + buildoutAreaName );
321+ //updateServerBuildout(self, sceneName, buildoutAreaName);
322+ return SCRIPT_CONTINUE ;
323+ } else if (command1 .equalsIgnoreCase ("setAllBuildOutObjVars" )) {
324+ obj_id [] objects = utils .getAllObjectsInBuildoutArea (self );
325+
326+ int count = 0 ;
327+ int addedCount = 0 ; // Count of objects we added objVar to
328+
329+ for (obj_id i : objects ) {
330+ //skip player
331+ if (i == self ) {
332+ continue ;
333+ }
334+ count ++;
335+
336+ // Check if the object has buildout objvar
337+ if (!hasObjVar (i , "buildout_utility.write" )) {
338+ // Set the objvar on the object
339+ setObjVar (i , "buildout_utility.write" , 1 ); // add objVar
340+ addedCount ++;
341+ }
342+ }
343+ sendSystemMessageTestingOnly (self , "Added buildout_utility.write to " + addedCount + " out of " + count + " total objects in buildout" );
344+ } else if (command1 .equalsIgnoreCase ("move" )) {
345+ if (!tok .hasMoreTokens ()) {
346+ sendSystemMessageTestingOnly (self , "SYNTAX: move <x> <y> <z>" );
347+ return SCRIPT_CONTINUE ;
348+ }
349+
350+ // parse floats from the command tokens
351+ float moveX = 0f ;
352+ float moveY = 0f ;
353+ float moveZ = 0f ;
354+ try {
355+ moveX = Float .parseFloat (command2 ); // we already had command2 as nextToken()
356+ if (tok .hasMoreTokens ()) {
357+ moveY = Float .parseFloat (tok .nextToken ());
358+ }
359+ if (tok .hasMoreTokens ()) {
360+ moveZ = Float .parseFloat (tok .nextToken ());
361+ }
362+ } catch (Exception e ) {
363+ sendSystemMessageTestingOnly (self , "Error parsing move coordinates. Usage: move <x> <y> <z>" );
364+ return SCRIPT_CONTINUE ;
365+ }
366+
367+ // get the target object
368+ obj_id target = getTarget (self );
369+ if (!isIdValid (target )) {
370+ sendSystemMessageTestingOnly (self , "You have no valid target!" );
371+ return SCRIPT_CONTINUE ;
372+ }
373+
374+ // get the target’s current location and move it
375+ location currentLoc = getLocation (target );
376+ currentLoc .x += moveX ;
377+ currentLoc .y += moveY ;
378+ currentLoc .z += moveZ ;
379+
380+ // set the target’s new location
381+ setLocation (target , currentLoc );
382+
383+ sendSystemMessageTestingOnly (self , "Moved target by (" + moveX + ", " + moveY + ", " + moveZ + ")" );
254384 return SCRIPT_CONTINUE ;
255385 }
386+
256387 return SCRIPT_CONTINUE ;
257388 }
258389
390+ public static int getCellIndex (obj_id cell ) {
391+ if (isIdValid (cell )) {
392+ return Arrays .asList (getCellIds (getTopMostContainer (cell ))).indexOf (cell );
393+ }
394+ return 0 ;
395+ }
396+
397+ public static boolean isWorldCoordinateOffset (String scene ) {
398+ dictionary d = dataTableGetRow ("datatables/buildout/buildout_scenes.iff" , scene );
399+ return d != null && d .getInt ("adjust_map_coordinates" ) > 0 ;
400+ }
401+
402+ public static String getHeaderFormat (String header ) {
403+ return "\\ #00FFFF" + header + ":\\ #.\n " ;
404+ }
405+
259406 // ===========================================================================
260407 // ===== getBuildoutRootCoords
408+ // - BMC: 05/07/2025 - keeping this function here as some other code may still be using it.
261409 // ===========================================================================
262410 public static location getBuildoutRootCoords (String buildoutAreaName ) throws InterruptedException {
263411 String buildoutAreaNumber = buildoutAreaName .substring (buildoutAreaName .length () - 3 );
@@ -395,5 +543,4 @@ public static location getBuildoutRootCoords(String buildoutAreaName) throws Int
395543 return new location (0f , 0f , 0f );
396544 }
397545 }
398-
399- }
546+ }
0 commit comments