Trying to make a new Disc Launcher type weapon....
Sami has expressed his desire for a Disc Launcher that has no splash damage & in the future would inherit the player's velocity. This is my first venture in to modding weapons; I think I have maxxed myself out on making maps 😉
I found the AVM Tutorial database, and it has many examples in it for all types of weapons. However, it seems like the information is maybe a little dated & jumbled up. I have not had 100% success yet with adding a weapon of my own making.
Does anyone know of a weapon Mod that was released with the modified .cs script files intact? I would like to look at an example like that & see how they made it work. I could then have a better chance at making the new Disc Launcher work once I see what all was changed from Base to the Mod. I don't want to "steal" anyones code; I just want to learn from it. I would give full credit in my weapons file to any original coders.
Comments
While I wouldn't say they're always the cleanest, almost every mod that isn't distributed in dso form should have an example of how a weapon being added/modified can work. Some of them do handle things like the inventory listing differently, but it's all the same in principle. Grab that mega pack of mod content and have a look through each one and you should find a few good ones, and a whole bunch of very rough ones that get the job done.
To add a new alternate spinfusor to alter those factors, you're mainly going to be creating new copies of a set of datablocks, making sure to give them new names:
ItemDatablock weapon itself, which describes the weapon as a pickup object in the worldItemDatablock for the ammo pickup, unless you want it to share the same ammo as the originalLinearProjectileDatablock to define the projectile and its parameters, where you'll apply the splash damage and velocity inheritanceShapeBaseImageDatablock, which describes the weapon in your hand and its behaviours. For a simple change, this will most importantly need to be updated to reference your other new datablocks: item, ammo, projectile.The easiest way to get started understanding how this behaves on your own server is just to change out the projectile datablock alone and reload the script, but because these are datablocks, you can't see the changes live without restarting the server unless
%client.transmitDataBlocks(0);is being run on your client every time the script is compile/exec'd. Some mods implement a reload("mydisc.cs"); function to do this for every client on a server.For more advanced weapon behaviours, you can start to look at state transitions and their script callbacks in the
ShapeBaseImageDatadatablock. "onFire" is the standard included trigger callback, and you'll seeShapeBaseImageData::onFirein projectiles.cs for the default action where the projectile is created. This can be completely overridden by creating a function with the same structure for your specific datablock, e.g.function DiscImage::onFire(%data, %obj, %slot)which can inherit the ShapeBaseImageData::onFire logic by calling%projectile = Parent::onFire(%data, %obj, %slot);You'll see a lot of examples of this if you look at one of the construction mods or something like Meltdown.Similarly, the projectile/explosions may have callbacks that are of interest for further advanced behaviours, e.g. having players within range of the impact have some special effect applied to them.
For actually adding it as a new weapon with how it's handled in the base scripts, you'll want to look at
weapons.csfor how reticles are specified to be sent to clients, andinventoryHud.csfor how it gets added to the inventory list for players to select. You'll also need to modify the player datablocks inplayer.csto set newmax[MyDisc]counts for inventory restrictions.If you don't want to bother going that far for testing a new gun, you can directly modify the disc datablocks to just try the changes on the spinfusor itself, or you can use
%client.player.setInventory(%datablockName, %count, %force);with theItemDatapickup block names e.g.MyDisc, 1, 1andMyDiscAmmo, 1000, 1Wow !!! 😎 Thanks for the quick response !!! 😊 I have a ton of reading to do now 😃 I really appreciate the advice !!! 👍️👍️
I'll go grab the Mega pack now & play around with it 😉
Using Krash's input on another thread, this is the function I've been using to reload mod changes. The last call binds the function to `ctrl + ;`. Refreshing the file manager is needed if you add a new
.csfile while the game is already running, otherwiseexec()will not be able to find it.function reloadModScripts(%a0) { if (!%a0) { return; } // Refresh file manager setModPaths(getModPaths()); // ADD YOUR SCRIPT EXECS HERE // E.g. exec("scripts/weapons/my_cool_gun.cs"); // Transmit datablocks to non-bots for (%i = 0; %i < ClientGroup.getCount(); %i++) { %client = ClientGroup.getObject(%i); if (!%client.isAIControlled()) { %client.transmitDataBlocks(0); } } } GlobalActionMap.bind("keyboard", "ctrl ;", "reloadModScripts");-Arg0
I just finished extracting the Mega pack to an empty directory. It looks like the Triumph mod has all of the .cs script files & I will be able to use those as how-to-do stuff examples 😃 Many thanks to the guys who put that together !!! 👍️
I also read thru the scripting FAQ included in the Mega pack...... Very good information & I am glad to have found it ☺️
Thanks for the advice & direction, guys.... I'll probably be back in about a month or two once I get all of this down pat ☺️
Well, after quite a few attempts I seem to have made some progress 😉 I am using the Triumph mod by PinkPanther as an example, as it has the .cs files included in the script directory. He made pretty good notes on his work inside the files, and the structure is easy to follow. I have tracked down all of the relevant files & WinMerge is a very helpful utility to use for seeing the differences between the original script file & the modified script file. These guys did a LOT of work 😃
I originally could not get the weapon to be visible on my arm; Now I have that fixed. My current issue is trying to get the reticle of my choosing to display when the weapon is called up & mounted on the player's arm. As of now, there is no reticle visible. I will continue changing one thing at a time until I figure it out.
I have tested the projectile at faster speeds & slower speeds to confirm that it is working, and boy was I happy when I saw that stuff was working perfectly 😁 I think in a few weeks I will have The Sami a unique weapon 😀
The best part of all of this will be that I am trying to keep it a server-side only Mod, available to only Human players. I do not know if that will be possible. If it is not, then I will have to start the tedious process of adding it to the bots 😐️
As long as you don't need things like custom models, keeping your mod server-side shouldn't be a problem. Custom maps do need any new interiors or custom terrains downloaded if you need them, but many maps just reuse existing assets.
Reticles are changed with the
setWeaponsHudActiveclientCmd (RPC messages sent to clients withcommandToClient), which is in part tied to some basic init inDefaultGame::setupClientHudswhen a client finishes loading: you'll see thesetWeaponsHudBitmapcalls which send$WeaponsHudDataentries for names and the hud icons to associate with each index slot. Remember to increment$WeaponsHudCountwhen you add your own$WeaponsHudData-- it's important to set these up in order for your preferred icon to be shown in the client's hud. The "itemDataName" you'll be using is the exact name of your ItemData datablock (e.g. MyDisc in the previous example), in order for it to map the lookup correctly.If you look over
clientCmdSetWeaponsHudActiveitself, you'll see that you can't apply custom reticles to the default ItemData datablock names, so if you want to override them on the server side you need to rename the datablock and serverside references to it, including the$WeaponsHudDataentries. What you'll also notice is that if you are not using a default datablock name, you can freely tell the client to apply any reticle bitmap, not just the one you've setup in the$WeaponsHudDataentry; essentially, if you wanted to implement custom mode switching or something where you wanted to change reticles dynamically, you could send thesetWeaponsHudActivecommand yourself at any time. You'll just want to keep track of the slot you've told the client to use for the hud icon.An basic example of extending the default set up of the entries in your weapon script as well as (optionally!) overriding the active reticle selection on mount could look something like:
if (MyDisc.slot $= "") { MyDisc.slot = $WeaponsHudCount; $WeaponsHudData[MyDisc.slot, bitmapName] = "gui/hud_disc"; $WeaponsHudData[MyDisc.slot, itemDataName] = "MyDisc"; $WeaponsHudData[MyDisc.slot, ammoDataName] = "MyDiscAmmo"; $WeaponsHudData[MyDisc.slot, reticle] = "gui/ret_disc"; $WeaponsHudData[MyDisc.slot, visible] = "true"; $WeaponsHudCount++; } function MyDiscImage::onMount(%this, %obj, %slot) { Parent::onMount(%this, %obj, %slot); // override the $WeaponsHudData sourced reticle that was just applied by the parent function commandToClient(%obj.client, 'setWeaponsHudActive', MyDisc.slot, "gui/ret_chaingun", "false"); }Note that rather than throwing the slot index info in a global variable, it's being stored directly in the datablock here. This isn't strictly necessary, and it doesn't have any special properties, it's just for your convenience.
Krash, thank you so much for the advice !!!!! 😉 I should have some more time to dive in to it next weekend !!! ☺️