Jump to content

ElPolloAzul

Premium Member
  • Posts

    31
  • Joined

  • Last visited

Nexus Mods Profile

About ElPolloAzul

Profile Fields

  • Country
    United States
  • Currently Playing
    None
  • Favourite Game
    Super Mario RPG, Freelancer, else heart.break()

ElPolloAzul's Achievements

Apprentice

Apprentice (3/14)

  • First Post
  • Collaborator Rare
  • Week One Done
  • One Month Later
  • One Year In

Recent Badges

0

Reputation

  1. Climbing is something Beth has never done...... Much as I would LOVE to be able to climb the rocks and such, in various locations, so far, no one has done it. Much as I wish they would. I think the animations are the stumbling block.... There is one guy that made ladders, but, I think those are workshop items, so, you can only build them in settlements, and they are not portable. (and I think you can only go UP.......) Hey now, they were climbing pioneers. In Daggerfall... The grappling hook's major problem is being able to dynamically change the BendableSplines used for the power wires in script. You could do a simple shoot to target mod (like the Anchorshot in my Keelerator mod) otherwise. The system is wayyy too slow to linearize the arc with your own line segment meshes or calculate physics a la Just Cause. The ladder issue is pretty much only an animations limitation. I imagine that a good paired animation system could even handle ladders with physics (i.e. potentially non-axis-aligned ladders) so that you could climb on the rotated coordinate system with the same animation. The free climbing issue is pretty insurmountable (har har) unless you had access to the source code of the game. It's not super easy to find adjacent meshes you are near and facing towards, check that they're big enough, check that the segment you're activating has at least a small mostly straight-up section across the triangles of the mesh and smoothly choose from a bank of animations or do IK for hands to do it right. If it was pure first person or you tolerated blinky type movement it would be easier but you would still have to have the climbing area detection routines. A number of climbing focused games had hand placed nodes or annotated meshes to speed up or cheese the process. Even stuck with Papyrus, you could certainly have the cartoony approach of spawning a constant length rope that you shoot which animates as dropping straight down and maybe sways a little in the breeze (canned animation). When you activate it, it puts you into "climbing mode" and you are translated up or down the rope depending on your viewing angle. You could even jump off to adjacent ropes by activating them, etc. But it would look like climbing a ladder in Minecraft. I did view-dependent elevation changes (albeit with an intermediate object) for my Elevator Pitch weapon in Angle of Mercy that allows you to throw a grenade and spawn an elevator whose translation forward is controlled by your position in the elevator, with the elevation controlled by elevation angle of your camera, and the orientation by the azimuth.
  2. Huh, since this got necro'd a bit: No, I just use the really bad editor in the CK with no frills for all of my Fallout 4 work. Once I wrote a script where I ran out of characters in the control and I just coded around that rather than switching, haha. However, absurdly, for Skyrim years ago I made my own mini IDE (I called it ReedWriter, geddit?), wrapped around a Scintilla.NET control in WinForms. It had syntax highlighting, compiler error redirection to a grid box so you could jump to the error, a function reference TreeNode view with the documentation scraped in an XML serialized record hive from the CK so that you could drag the function signature into the editor and in a tooltip see everything about the function or so forth from each Script Object down to the related Events and Functions (and a GUI record editor in case you wanted to update with F4SE or your own functions), a secret easter egg that referenced Tribunal and menu items to run external tools on the script or its results (like the disassembler), plus find+replace with highlighting, goto line numbers, and some other weird stuff. I never released it since I was too lazy to even change the expected files over from Skyrim to Fallout 4 :rolleyes:
  3. Yep, while guaranteed to be janky, practically any amount of "control" of the turret is possible, even without F4SE, if you are determined enough. Take a look at these stupid things I've done. Garbage DeflectorPossess arbitrary grabbed junk items and hop them about with the camera. Zetan PoltergunPossess actors, but the camera is worse than the early PS1 era because you have to follow around like a ghost. Interaction is limited just like possessing wampas in Shadows of the Empire on the N64. The console command possession is a little different, but not accessible outside that. Angle of MercyLook at the Desktop Gun in this for a different spin on control. You use holotapes to coordinate swivel gauss rifle terminals. Designate a target while crouched and all of your turret stations will fire in unison on the target when not crouched. Explosive when Fat Man projectiles are used. The Remote Hewing axe and the Ghost Iron in The Sky autonomous flying revolvers show other uses of camera control and creative use of the Weapon.Fire() function.
  4. This seems like a problem with Object Mods and object instances, so at a high-level (to get your "modless" base weapon): The exclamation, inventory star, and item feature screen comes about usually as a result of your Weapon record having the FeaturedItem keyword.You should make sure that the gun is the Default (there's a checkbox on the Object Instances screen) and only instance from the form. Otherwise the loot generation system will pick a random gun from the "prototypes" (don't know what the actual term is) you have in the left-hand list box (e.g. pipe gun owns pipe rifle and pipe pistol, etc. prototypes). Prototypes can actually have composite Object Mods attached to them that are lists of Object Mods to randomly choose from in turn.The extra "Pistol" is a result of the instance naming system stepping in, often as the result of a dn_ style keyword being added by one of your Object Mods. Remove that addition to the relevant ObjectMod (look for directives like ADD or SET that have a keyword that they add) -- but make sure that the ObjectMod/"part" you are editing on the object instance is a copy and not a base game form or you will be removing Pistol for a lot of pistols in the game and breaking other things.To force flavor text and a Legendary effect onto the gun, you can often take your default instance and add a new "part"/Object Mod. Make a blank Object Mod and check its Legendary box. Specify that it applies on a Weapon. Add the ap_mod_Legendary attach point. Name it uniquely (Andyno_LegendMod_Pistol). Add a description if you want one in the feature screen and on the side of the object's description readout in your PipBoy. Make sure it does not have a default mod item or a recipe (since you want to put it in the world). Don't add any mod keywords (ma_) if you want it to not show up as a part for other guns at the Weapons Workbench.(Later, you can add non-legendary Object Mods with a new mod association keyword you create, but with valid recipes and in-world mod items if you want the mod pieces to be constructible. If you want to put default ones on the instance, add these Mods as parts to the instance -- but you don't need to).Finally, at the main Weapons form, make sure you add the ap_mod_Legendary attach point to the weapon. This should work even for thrown weapons (grenades). Also, you can play with Weapon attributes such as making the thing non-hostile, providing an override projectile, having the weapon use no ammo at the cost of having no VATS, or making the thing not playable for the PC.P.S. If you are testing the mod, load a save before the mod first loaded the gun in your world, because once the object instance generation system makes a weapon, some of the changes are in the savegame and won't be changed by your plugin edits.
  5. If you set the variable's owning script to be const, then you have to set the variable itself to be const (all properties must then be const). This is checked by the compiler. The const value is meant to be constant (changed only in the initialization in the plugin form in the CK and no further). So if you don't set const, then you can change the variable from either the object itself (some function attached to the object, named either by DTAG_Radius, or by self.DTAG_Radius) or from a foreign object that knows both the formID and the type of the object (if you know the type from a different script, you should cast the foreign object reference before using (e.g. SuperElitist:DTAGObject dtag = randomObjRef as SuperElitist:DtagObject; dtag.DTAG_Radius = 3.14159265). You can even load objects from other plugins which are not loaded in the plugin you are editing (using GetForm and CastAs) and mutate their properties as long as you know the formID of the object, the type of the object, and the method or property to be used. Obviously, if you change the value before the script is run, you won't necessarily be doing much that is useful. The variable will probably be initialized but not to the value that "makes sense" based on what you are planning. You can initialize the value either in the declaration (e.g. Int Property MagicNumber = 2.71828 Auto) in which case it will be available from the beginning, once the mod is loaded, before any events are captured, or subsequently/after, in response to a naturally useful Event, such as OnLoad (Event OnLoad() \ dtag.DTAG_Radius = 0 \ EndEvent). In short, you can definitely change property values (as opposed to local variables, declared as, e.g. int DTAG_Radius = 0) from outside the object and have the change represented in the save. Admittedly, the CK wants you to declare forms and thus all their owned properties as const by default. You can safely ignore this. Specifically, you can create a new script in the CK and edit it to remove the const keyword. Then you can declare properties that are not const, despite what the GUI wants to set up for you. If this did not work, then scripted objects would only be able to refer to properties that were held in common for the whole class (in other words, individual instances would not be able to retain their own data).
  6. I'm also kind of exceptionally surprised if this has not been done. This was one of the ideas I was considering for Skyrim weird weapons, and I think your high-level design is the correct plan. As to your (A), the scripting should not be a problem -- but there are always setbacks when things don't work quite as you imagined from the documentation. The selection power itself is easy to construct, aside perhaps from getting the generic nature of the NPC. The quest and book delivery part is even easier. Random dead drops from a small list of hidden boxes chosen to be close to the target or even the conversation with the generic DB rep to process payment wouldn't be hard either. Two points are interesting from the programming perspective (there may be differences depending on what wasn't in Skyrim but was in FO4, but I think you should be able to do all of this without the Script Extender and be on XBOX too for SE). This is what I had imagined: Orchestrating the murder. Probably this would be faked/cheesed a little depending on if you were around to witness things (if you've played the space sim X3, there are wildly different combat mechanics for ships that are OOS, or out-of-sector). You could have a specific generic murderer or a pool of murderers who fall with mutual exclusivity into a specific Alias with a package to go to and stalk the NPC. You poll around from something else, waiting for the NPC to be kind of close (same Location or cell) to the target; you can do this out-of-loaded-area if you are just looking for something very approximate, not involving most kinds of distance checks. If you as the Player are not there, you can cheat and send a Kill event with the necessary details (e.g. the murderer) to the victim. If you are present, it gets more interesting. You could have the NPC path to or AI package to the target and StartCombat with them. In my Kids Eat Free weapon for Fallout 4 which spawns child serial killers who stab people with rippers, I used paired animations to make the murders more explicit -- ripper to the gut -- but they are more finicky than just a StartCombat, as the NPCs have to be positioned just right for the animation system to accept this. The victim targeting was supposed to be random and work for arbitrary numbers of present targets and murderchildren, so I couldn't use a central Alias for the targeting -- it is appropriate to only have one Black Sacrament murder running at a time. It would be more trouble than worth for the assassin to have to sneakily kill the target, or do it by a specific means, such as magic. When the target is detected as dying or gives off the dying event to its alias or by some other means, you can trigger the rep or a nap or even maybe the game's normal Courier (less advisable for uninstallation maybe) to give you the note. Doing the Black Sacrament. It would be unnecessary but also pretty damned interesting to have to actually do the black sacrament in an arbitrary location. The unconstrained geometry problem of the spell or a vendor giving the player special candles that have to detect in a distributed fashion that they are encircling the necessaries is annoying as heck, so you would want to take a hard pass on that. Give the player an item that would black out the screen and spawn a circle of candles when a master controller item (maybe with no significant 3D) is dropped. Then the invisible or visible master controller object could check periodically if ritual ingredients were close when the player is there. It could trigger FindNearestFromRef type queries to be sent from each candle in the circle towards each necessary body part (bones and flesh). The consensus/modal (most-common) body part of each type returned out of say 10 candles offering a ObjectReference could be checked to see if it was in the circle, which is completely trivial if you are using a check within an exact circle rather than an approximate circle because you have the closed form constraint used to generate the circle that the candles lie on -- then do a height check to make sure that the bones are not on the floor above the 2D circle, etc. If all necessary parts are there, an OnHit event attached to the ribcage or similar items (maybe even the union of body parts, each updating your master controller with valid item counts) could see if you were hitting with the proper weapon. A DB rep NPC could sell or give you the enchanted dagger, and maybe you would have to equip it with nightshade in inventory or something before it could become the real dagger required by the ritual. Just put a message on the screen with the Black Sacrament text instead of triggering vocalizations, or make a ghostly voice version of somebody generic and Lucienlike intoning the exhortation. This detail may all be overkill, but it is cool overkill -- letting the player experience the Sacrament is the key to this. It would be interesting to get some sound and voice and maybe evil lighting into the rite. Don't know about your (B), which is how much people would actually care about this now. In 2012 or 2013, I imagine this would have been a pretty cool mod for people. It would have to be pretty cool to go through the writing and script testing that you would need to go through to make it happen -- some new voice lines with nonoriginal DB characters could make it better or you could stitch some very minimal responses together from an existing DBer. The total complexity of the project is something I would see as pretty darn manageable (prototyping a version without the writing and sound polish would probably just take a couple days or maybe a week if everything necessary was still there as I imagine it), but I have tried to do intricate things in these games and some of them were really time consuming (implementing a Tetris clone and a in-game scripting interface, a maze generator, etc.) to test, so I might not give a realistic normative feasibility estimate.
  7. You can refer to the water plane (it is usually a placed object) and translate it down (e.g. TranslateTo, SetPosition) by script. This is the approach I used in my Bilgeplump mod, which I was actually inspired to make by a private mod I had made for Morrowind many years ago (there as in I think Oblivion, the water was based only on which cell you were in, and in the former, there was a script command for moving this at runtime). Others would probably think I derived inspiration from the Weston Water Treatment plant, or the Dwemer ruin in Dragonborn (Nchardak?).
  8. Linked lists are only feasible with the lack of pointers in that you are allowed ObjectReferences. So the implementation necessarily involves the creation of "physically" instantiated objects (whether they are activators or MiscObjects) somewhere in the game world. It's not too surprising given that the save game format largely mirrors the plugin format in some parts and everything is tied to records. I think that the array limitation might have been viewed as a good thing in some behavioral sense. If you have to consciously resort to these shenanigans, you *might be* less likely to just create unbounded arrays and request hilariously too much space in a savegame with a bad loop (very easy to write). Across a mod ecosystem with lots of different authors, chasing down lots of memory without an accounting of who owned it (the accounting tight coupling with a record/OR/RefID implies) might be unpleasant. So there is a maybe unintended protective effect of Bethesda's choice here. FormID exhaustion could be a realistic problem, but pretty much every effect and short-lived entity (including some projectiles?) in the game uses one, so the long-term sustainability problem is potentially there anyway. It matters what the real consequences of invoking Delete and other tools are, and in turn, it matters what solution BGS actually used in between now and original Oblivion. Some people who have been here for Shivering Isles remember the reference bug triggered at least by the Golden Saint guards in Mania's Greenmote Silo. The patch for that bug introduced a new-at-the-time method for recycling ephemeral FormIDs in the FF range that reportedly also used some of the unallocated, unloaded sub-FF range. In SI, though, the scripts were generating at least several RefIDs per frame! So the linked list possibility using the cheesing approach is not just academic. From an old and less tested version (that still bears the very ugly debug comments and I'm quite sure obvious bugs) of the script in Papyrus Computer Club: Scriptname PapyrusGun:EPAArrayList extends ObjectReference var[] Property raw_array Auto PapyrusGun:EPAArrayList Property nextSegment Auto PapyrusGun:EPAArrayList Property tailSegment Auto int Property currentSize Auto int Property currentCapacity Auto int Property currentSegmentCount Auto bool Property isHead Auto ObjectReference Property monadRef Auto Const MiscObject Property BreadBoxProto Auto Const Function Initialize() self.nextSegment = None self.tailSegment = self if self.isHead currentSize = 0 currentCapacity = 100 currentSegmentCount = 1 else currentSize = -1 currentCapacity = -1 currentSegmentCount = -1 endif self.raw_array = new var[100] EndFunction PapyrusGun:EPAArrayList Function ConstructMe(ObjectReference localMonad, Form arrayProto, bool makeHead) global PapyrusGun:EPAArrayList newRef = localMonad.PlaceAtMe(arrayProto, 1,1,1,0) as PapyrusGun:EPAArrayList newRef.isHead = makeHead newRef.Initialize() return newRef EndFunction PapyrusGun:EPAArrayList Function DestructMe() int segmentIdx = currentSegmentCount - 1 while segmentIdx > 0 GetSegment(segmentIdx).DestructMe() segmentIdx -= 1 endwhile self.Delete() EndFunction int Function RFind(var object) int objFind = -1 int segmentIdx = currentSegmentCount - 1 while segmentIdx >= 0 int candObjFind = GetSegment(segmentIdx).raw_array.find(object) if candObjFind != -1 return Math.Floor(segmentIdx*100.0 + candObjFind) endif segmentIdx -= 1 endwhile return objFind EndFunction int Function SequentialFind(var object, var[] arrayObj) global int arrayIdx = 0 string stringObj = object as String Form formObj = object as Form while arrayIdx <= arrayObj.length - 1 if stringObj == arrayObj[arrayIdx] as String return arrayIdx elseif formObj == arrayObj[arrayIdx] as Form && (object as Form != None) return arrayIdx ; elseif object as Int == arrayObj[arrayIdx] as Int && (object as Int) > 0 ; return arrayIdx ;elseif object as Float == arrayObj[arrayIdx] as Float ; return arrayIdx endif arrayIdx += 1 endwhile return -1 EndFunction int Function Find(var object) int objFind = -1 int segmentIdx = 0 while segmentIdx <= currentSegmentCount - 1 int candObjFind = SequentialFind(object,GetSegment(segmentIdx).raw_array) if candObjFind != -1 ; debug.notification("Find at " + segmentIdx + ": " + candObjFind) return Math.Floor(segmentIdx*100.0 + candObjFind) endif segmentIdx += 1 endwhile return objFind EndFunction PapyrusGun:EPAArrayList Function GetSegment(int segmentIndex) PapyrusGun:EPAArrayList traverser = self if segmentIndex >= currentSegmentCount ;debug.notification("Segment fault " + segmentIndex) return None endif int segmentIdx = 0 while segmentIdx < currentSegmentCount && traverser != None if segmentIdx == segmentIndex return traverser endif traverser = traverser.nextSegment segmentIdx += 1 endwhile ;debug.notification("Couldn't find segment " + segmentIndex + ": " + segmentIdx + ":" + currentSegmentCount) EndFunction var Function GetAt(int index) if index >= currentSize return None endif int segIdx = Math.Floor(index / 100.0) int partIdx = index % 100 var returnObj = GetSegment(segIdx).raw_array[partIdx] ;if returnObj as String == None ; debug.notification("Fetching object @ " + index + "," + segIdx + "," + partIdx) ; endif return returnObj EndFunction PapyrusGun:EPAArrayList Function BlockCopy(int indexStart, int indexEnd, PapyrusGun:EPAArrayList destArrayNew) if destArrayNew == None ; debug.notification("Empty Array") endif ; debug.notification("BLOCKCOPY " + indexStart + ": " + indexEnd + " of " + destArrayNew) int capNeeded = indexEnd - indexStart int segCapNeeded = Math.Floor(capNeeded / 100.0) PapyrusGun:EPAArrayList destArray = destArrayNew;PapyrusGun:EPAArrayList.ConstructMe(monadRef, BreadBoxProto, 1) int expandIdx = 0 while expandIdx < segCapNeeded destArray.ExpandArray() expandIdx += 1 endwhile int segIdx = Math.Floor(indexStart/ 100.0) int partIdx = indexStart % 100 int lastSegIdx = -1 int lastPartIdx = -1 int traverserIdxIn = indexStart int traverserIdxOut = 0 int segIdxOut = -1 PapyrusGun:EPAArrayList curSegIn PapyrusGun:EPAArrayList curSegOut while traverserIdxIn <= indexEnd segIdx = Math.Floor(traverserIdxIn / 100.0) partIdx = traverserIdxIn % 100 if segIdx != lastSegIdx lastSegIdx = segIdx curSegIn = self.GetSegment(segIdx) segIdxOut += 1 curSegOut = destArray.GetSegment(segIdxOut) endif curSegOut.raw_array[traverserIdxOut] = curSegIn.raw_array[traverserIdxIn] destArray.currentSize += 1 traverserIdxIn += 1 traverserIdxOut += 1 endwhile ; debug.notification("DESTARRAY SIZE " + destArray.currentSize) return destArray EndFunction Function SetAt(int index, var obj) while (index + 1) > currentCapacity ExpandArray() endwhile int segIdx = Math.Floor(index / 100.0) int partIdx = index % 100 GetSegment(segIdx).raw_array[partIdx] = obj if index >= currentSize currentSize = index + 1 endif EndFunction Function ExpandArray() tailSegment.nextSegment = PapyrusGun:EPAArrayList.ConstructMe(monadRef, BreadBoxProto, 0) tailSegment = tailSegment.nextSegment currentSegmentCount += 1 currentCapacity += 100 EndFunction Function DebugPrint() debug.notification("Item Count: " + currentSize) debug.notification("Item Capacity: " + currentCapacity) debug.notification("Segment Count: " + currentSegmentCount) EndFunction Function Push(var obj) while (currentSize + 1) > currentCapacity ExpandArray() endwhile int insertIdx = currentSize self.SetAt(insertIdx, obj) EndFunction var Function Pop() var thingContained = self.GetAt(currentSize-1) self.SetAt(currentSize-1, None) if currentSize > 0 currentSize -= 1 endif return thingContained EndFunction int Function PareDown() int segmentIdx = currentSegmentCount - 1 int segmentsTossed = 0 while segmentIdx > 0 if (currentSize+100) < currentCapacity segmentsTossed += 1 currentCapacity -= 100 GetSegment(segmentIdx).DestructMe() endif segmentIdx -= 1 endwhile return segmentsTossed EndFunction That's why a community effort to produce a well-tested native data structures library might be useful (if Starfield or ES6 reuses Papyrus). As for the structs, you can make a similarly embodied MyRecord type class that has all of the same fields -- it's true that there was an array restriction on structs! Also, I feel like Papyrus is closer to a pared down Java (single inheritance, variable references, bytecode, garbage collection etc.) than a pared down C++.
  9. Yeah, that makes things less convenient, but luckily you can still put elements of variant type into the array. In your list segment data structure class, you can have this: var[] Property raw_array Auto If there were no var arrays legal in Papyrus, there would have been no way to expose nearly all Papyrus functions to an in-game programmer using CallFunction. You can either grab the objects out as you go and fetch the type with a chain of is statements (probably pretty expensive), or if the list is carrying things of homogeneous type, you can embed some logic into the "constructor" which does this once and then sets a type int or string field or similar which tags the array's type. Concept if not implementation overall is kinda like a tagged union. Fortunately, most of the "indispensability" of generics comes about when you are doing usually-horrid things like having nested generics (we've all committed some atrocities for fun). I wouldn't recommend it, but for stupid fun there are two very dumb remedies potentially feasible if you are committed to merely a constant total capacity that just happens to be larger than 128. You could make an extended/jumbo array class that holds a few hardcoded arrays (Scriptname UtilityJunk:MondoArray extends ObjectReference) and provide your own functions for doing things (as you would have to with the linked list approach, using mod to find the correct raw array index), or (oh, far worse) you could use two global collections of FormList etc. type (one heap list contains all extended list objects ever, and the other header list contains the ranges of "lists" in that list, and each user maintains a id to the "list" they want to use -- like a handle vs. a smart pointer reference system). Linked array lists aren't that bad to implement, even in this less-than-ideal environment, and if I had lots of time to write and debug and was confident that native Papyrus would continue to be useful, I guess I would probably have rolled up a library of all the common ADTs (graphs, trees, stacks, queues, priority queues, deques, maps, sets) as a modder's resource. For my own stuff, the maps I just used with sequential search because I had very few keys although it would have been pretty trivial to set up a hashmap for performance. As a community project, there could be a lot of potential for testing and visually benchmarking design choices in such a library.
  10. Yep, FormLists and the like are probably a good solution for you. I've specified them in-editor past any theorized 128 element limit for sure. The issue presumably comes in when you need dynamically allocable lists (not just pre-created lists) of dynamic size within a script. For that, I've detailed my highly circuitous approach to that in a recent post: https://forums.nexusmods.com/index.php?/topic/7683768-tracking-container-contents/
  11. Yeah, there are a lot of annoying glaring holes in the scripting system, and those are at least two of them. You can get around this, but it isn't particularly pleasant and requires some ingenuity. It's fun if you are a masochist! For my Papyrus Computer Club mod (that arrived too late for anybody to be aware of), I built an in-world terminal out of paper letters and an in-papyrus interpreter for a very simple BASIC-esque domain-specific programming language so that you can shoot people with programs that you write in game and which are saved to your savegame so that you can do this even on Xbox. To do this required having indexable and modifiable strings, which we also know the game doesn't support. So what I did was create a new EPAString class that derived from an EPAArrayList class, with the former having a small number of string operations like the C Standard Library that I rolled my own on. The EPAArrayList is an object that contains a native Papyrus array and also ObjectReferences to another EPAArrayList. It can be marked as the head node or not the head node, so you may correctly expect that it implements a linked list of arrays. It's a mix between a linked list and a Java-like ArrayList (the list has both a length and a capacity at any one time, with some of the array being dynamically allocated space). You may note at this point that you can't construct objects arbitrarily in Papyrus, because all memory use should be tied to object records. So what I did was create an empty utility cell, place an constant global ObjectReference there as an anchor or monad and use it to spawn physical objects in the void, one for each necessary logical object. EPAArrayLists were breadboxes, EPAStrings were spools of string, EPAStoredPrograms were holotapes, and so on. In this way, I actually used some of that experience implementing data structures from my time in computer science at university. The stored programs were simply array lists of strings with a program counter and a shallow or deep copy operation for managing separate instances of the programs under an interpreter routine. There was a lot of fuss laying out the virtual keyboard as positions hardcoded into the NIF file and managing the character set conversions (arithmetic change of base formulae were in this to handle specifying floating point numbers, also used in the Form F From Address Space mod) and so on... You can't even hardcode a string to be used, so you have to write a separate program to generate Array.Add instructions for any strings you want to hardcode in the system. I also reused these native linked list objects in Mirelurk Merchant (needed for an l-system interpreter that expands the fractal patterns in parallel in-game so they aren't hardcoded in a giant script file), The Maze Ruiner (needed to hold the matrix holding the structs specifying the hedge maze cells and their wall states), and Falling Down (used to construct the Tetris-esque board, but not used to run it because the member-variable lookups were too slow, so I used native Papyrus arrays for hardcoded columns to speed up the computation to where it was semi-playable). Falling Down was also my first script that almost didn't fit in the text editor dialog used in the CK.
  12. One of the great sad truths about society is that it assigns value almost pathologically poorly from the humanistic perspective, and it does this much more efficiently and perniciously than a single person, however misguided, ever could. A lot of the very most stupid and inconsiderate kids many of us despise growing up turn out to live pretty nice lives while the rest of us in some sense fritter opportunities of youth away caring about various people and issues and cultural products and bodies of knowledge and jeremiads that are important to us at the time, as opposed to simply advancement. A few of Those who don't Care stumble through a semblance of higher education, just having "fun", occasionally with all of the shockingly stereotypical trappings and interpersonal abuses you'd expect, and end up as decently-paid "business development" "professionals" who get to spend their careers swarming around any identified artifacts of aesthetic value or people of competence they are directed to, hoovering them up in an intellectual property version of the historical practice of enclosure, and devouring nearly everything good or interesting about them. This happens in some way to everything that's visible enough of a target for commercial overexploitation because there's not much of a concerted mass movement afoot to identify and extirpate these personalities from the positions of influence that they are intent on inhabiting or from society at large. Enough soulless marketers or "strategists" come to roost can and will kill any good thing and disband any assemblage of talent. You cannot realistically expect many of these types to exhibit gratitude, humility, authenticity, or charity in their professional lives either and it is notoriously hard to clear them and their ideas out from organizations and affiliates, even if their ideas strangle and kill organizations, ultimately destroying shareholder value. Like any infestation, they tend to bring their friends. I think that regardless of our various disappointments at some number of missed opportunities, the core team at Bethesda Game Studios isn't at all in that territory, and has been doing something "special", that is, reasonably miraculous and not successfully replicated at scale by anyone else for many games in a row. Until recently, they have weathered runaway success (which is typically ruinous) reasonably well. Their dominance of a particular type of highly-engrossing, zeitgeist-type game is more like Rockstar North's old situation and less like the golden ages of Westwood or Maxis or DICE or Bioware or Blizzard. Nontechnical people talk all the time about replacing the engine with something more-or-less off-the-shelf (Crytek! Unreal!), but don't really seem to get that the engine that's there has a unique combination of competencies built-up over time in a Ship of Theseus scenario. If you want to understand how engines evolve, and sometimes form, direct, and outlast companies, just look at the legacy of the Quake family of engines. "Bethesda games" take on interesting technical challenges not often confronted that won't go away just because someone else has chosen to take them on. Unfavorable comparisons to more on-the-rails games (even if they are open world!) with better animation systems, particle effects, inverse kinematics or facial animations will always be substantially invalid: these are massively object-oriented, highly-interactive, simulation and dynamics-heavy monsters with a whole lot of data, entities, and moving parts. When you have to design and then model the logical consequences of these elements interacting, the complexity grows combinatorially. Furthermore the mechanics, the art assets, the writing, and the worlds have a LOT of emotional expectations set upon them -- they aren't peripheral grass or water simulations in a racing game. Both of these facets (the technical and the emotional complexity) conspicuously keep the modding community for these games busy for many more man-years than could be profitably sustained in commercial development. Ultimately, there are tradeoffs in response to resource, time, and core competency constraints -- you can look at the X series by Egosoft to see what some games developed with a skeleton crew which embrace (re)invention of a franchise-specific engine and their players are capable of sacrificing in the pursuit of a rarefied level of systems-heavy gameplay. When you see a nice, shiny, stable game, you also have to ask how much of what's good about it comes from the root of a reused engine, vs. how much is bespoke and project-specific. Beyond that, in the current situation with BGS games, you have a community of highly acculturated tool users and content creators that is almost entirely alone in the world, in its own class. It elevates regular players to mod creator at a greater rate than nearly any other mainstream game. That shouldn't be thrown away lightly. Outside the games industry, untold millions have been lost and ventures and careers abandoned due to needlessly reinventing relatively simplistic healthcare records, accounting, and educational software and then thrusting it upon scattered groups of bewildered users who need to be very expensively trained. Their throwing more bodies at an foundational overhaul isn't necessarily going to improve things: the Hollywood/Ubisoft-game model of throwing thousands of very-short-term workers at a project to get it produced faster produces beautiful art assets quickly and assembles worlds fast when well orchestrated (and that orchestration is a marvel) but doesn't tend to work well for producing a cohesive piece of complex software or an organically iterated world where there is a lot of interrelated stuff to do. It is true that a lot of indie devs regularly inflict hardship on themselves to produce a few polished gems, but the relative brevity of the credits for Morrowind, Oblivion, and Fallout 3 especially is still impressive. Alone, it is impressive how many users of Papyrus there are compared to how many were likely involved in its development. Perfection is easier to aim for in circumscribed, initially-despotically-led freeware projects with unconstrained development schedules. Bad or not, Havok is largely the same physics middleware used by nearly everyone and so a lot of games have been replete with its hilarity. The cart of cabbages is decent microcosm: here you have an odd corner case where the dynamics of the physics system lead to a runaway situation. Overall, among flaws crying out to be fixed, it's low priority: It's pretty funny, it generates some press, and a lot of viral videos. A whole lot of other games would have made the cart a static object and called it a day. They would have never had to deal with this kind of criticism, but the carts in the game would also be completely unremarkable. It's hard to justify finding the expertise to evaluate and fix all of these things (if they can be fixed -- at some level of simulation, these become potentially insoluble empirical problems), because if you strove first to produce a bug-free game, you would never succeed, and it is time spent circling the drain that you would not be putting out a new creative work, thinking about innovations, cool little details, and so on. Nintendo's internal studios pour immense resources into polish and QA, plan as if they had still had one chance to "go gold", typically shun including complex systems "just for the heck of it", target homogeneous hardware they don't have to scramble to support around release day, don't allow or allocate resources for modding, don't have a lot of background dialogue and map filler and multiple paths to completion and AI-centric scheduling in their games, and correspondingly have a great release quality track record, but they still have showstoppers (e.g. in Skyward Sword) and have somewhat embraced the patch and DLC culture. BGS catches quest bugs with a bit of a lag and less completely than is really ideal, but arguably you should be comparing their changelogs to games of comparable complexity (some MMOs, and Minecraft, etc.). To understand why choices with a lot of alienation potential (online and mobile plays that could be described as cynical) don't kill a developer like this, you have to ask "Why do people like fixing these games?". Many of us love BGS games despite anemic main quests, for example. It has been implicitly demonstrated, then, that while we would really like improvement there, it isn't our priority. So are the bugs even a top-5 priority as consumers, especially considering that the first wave consumers are the more important, rather than the die-hard realism and fixes folks who inhabit the long tail? I do think the games have to be said to succeed pretty well while not being fixed (before the CK comes out, and historically indefinitely on consoles with no recourse but official patches, which previously had to go through an expensive and hardly agile certification process demanded by the likes of Sony and Microsoft). Also, how many people can justifiably take credit for fixing the games? Who's "we", really? The small percentage of prolific mod authors out of total players, and the percentage of bugfixing mod authors over those mod authors (many of whom want to just get something out there that others can enjoy) should maybe be more regularly considered when this argument is made. While I think it is the right thing to do and the smart thing to do to meaningfully respect and incorporate and maybe even reward modders, most disrespect they are exposed to does not originate from Bethesda, and they are a more agile and larger collective, so they will always be fixing faster than the devs if they are motivated and given usable tools. I think it would be interesting to know what the real opinions of development studios were among different kinds of other developers, as opposed to the gaming public (which still funds modern-day Activision & EA, and deals with collective action so very poorly).
  13. If you are using just MoveTo (as opposed to doing MoveTo to do a relocation to the player's cell and position and then a SetPosition based on the new absolute coordinates you compute), I think those offsets should be then relative-to-the-target (not incorporating player position) rather than absolute. There's an example of these semantics on the Creation Kit wiki for Skyrim (but amusingly not the Fallout 4 page?): Actor PlayerRef = Game.GetPlayer() Portal.MoveTo(PlayerRef, 120.0 * Math.Sin(PlayerRef.GetAngleZ()), 120.0 * Math.Cos(PlayerRef.GetAngleZ()), PlayerRef.GetHeight() - 35.0)
  14. 1.) For one thing, you are positioning the spawning marker with SetPosition(), which changes the coordinates of an ObjectReference. Each worldspace (and interior) has its own coordinate plane. You might want to use MoveTo to relocate the marker to the Player (this takes into account also the cell & worldspace of the target reference). If there's just a coordinate change, you are likely plopping down your actors close to the middle of the Commonwealth map when you are in, for instance, interiors. 2.) Random seems to refer to a variable you declared (Float Random), but did not intuitively define. You do assign a value in the body of a function also called Random(), but is this function called per random deviate you want (x and y) to generate? Also, if you wanted to immediately get the return value of the function and add it to the result of a GetPosition call, you would want to declare your function as such (float Function Random() and explicitly return the value of Utility.RandomFloat(250,500)).
  15. To me, "modder" in the video game software sense will always be set aside to describe a person who designs and implements ("develops") a suite of changes, however simple, rather than "merely" applying them. Above and beyond a clearly-made producer/consumer distinction, there has to be some devising work that is more on the creative/design side, and less on the QA side. The people who PEEK-POKE probed memory and wrote those trainers were always socially and often linguistically differentiated from the people who just downloaded them and dodged trojans while doing so. I think that a decade or more ago, the distinction between modder and user used to be a consensus thing around here, but some trends intervened. One of them was that, certainly, in online console games (particularly FPS), "modder" became used as an epithet targeted at someone who used an exploit or was skilled or lucky enough to look like they did. In some rare cases, those accused actually bought or otherwise acquired knowledge of a real exploit from an original "hacker" (a word that went through its own de-evolution from the perspective of the early MIT AI community). And on the hardware side, those who sent away their consoles to strange people on the internet to be "modded" to allow loading homebrew software started to be called "modders" in league with the kind of conspicuously-tinkering "maker"-type people who would actually create their own console form factors and custom peripherals. I think the line was originally blurred a bit in the "tuner car" culture, where you surely have a whole ecosystem of aftermarket custom parts, but the level of investment (in time, money, and know-how) led to pretty personalized, self-expression-laden combinations (there isn't as much of the "what's an essential list of body mods and the ideal paint combination in 2018?" kind of discussion there). And I think that part of the motivation for the change was that there wasn't a really conspicuous word for mod enthusiast, the kind of person who spends thousands of hours consuming hundreds of mods, because the numbers simply didn't support that kind of person existing at scale. I think there really didn't need to be, then, because outside of domains like novelty FPS maps and skins shared across servers, the mod consumers and makers were blended together a lot closer in tighter-knit communities with a lot fewer mods which required a substantially more technically-inclined, more-generally-out-of-mainstream audience, at least to develop. I think of the collections of regular forumgoers on places like StarWarsKnights and LancersReactor and corners of gamedev.net, and of those who would leave elaborate "guest register" comments on people's personal free-hosting sites. Just like you see still for games with not much in the way of modding tools (beyond the trusty hex editor), there was very little attempt on the part of a large consumer community to support critiquing and running a bunch of mods at once (if you REALLY wanted to merge certain Freelancer mods as a user, you had to deal with reassembling string tables in (trivially) encrypted DLLs, and matching those to merged records of objects in sectors -- it was helpful to be an accomplished computer programmer just to use mods). Finally, as others mentioned, there is inevitably the usual, "am I really a X?" question that happens whether X is scientist or programmer or writer or artist or musician, and you don't have much of a portfolio in the dabbler stage.
×
×
  • Create New...